【问题标题】:PHP classes, inheriting, implementsPHP 类、继承、实现
【发布时间】:2011-11-29 15:09:32
【问题描述】:

我正在查看Should I use multiple classes for game? - Robert Pitt 的回答。

interface Weapons {

    public function Fire();

}

class Colt implements Weapons {

    function Fire() {
        echo 'Fire!';
    }

}

abstract class Human implements Colt
{

}

class Sniper extends Human
{
    public function __construct()
    {

    }



}

我可能在“人类”上实现“武器”而不是柯尔特,然后在“狙击手”上初始化右武器类?

class Sniper extends Human
{
public $weapon;

    public function __construct($weapon)
    {
    $this->weapon = new $weapon;  
    }


$this->weapon->fire();


}

或者类似的东西?我对它的工作原理感到困惑..

EXAMPLE 1

class A {
public $class;

__construct() {
$this->class = new $class;
}

hello() {
$this->class->hello();
}
}

class B {
public function hello() {
echo 'hi';
}
}

【问题讨论】:

  • 类 Human 应该 extend,而不是 implement 类 Colt。因为不是界面
  • 这完全取决于您。如果您在一家拥有自己的最佳实践清单的公司工作,那么您会询问和阅读文件。但既然这是你的项目,那就去做吧。最好的学习方法是犯错。

标签: php


【解决方案1】:

这取决于你,你将如何设计你的课程。

如果我是一名游戏程序员,我可能会使用类似的东西(这是一个可以工作的迷你游戏!)

<?php
class Fight {
     public $weapon;
     public $name;
     public function __construct($weapon, $name)
     {
        $this->name = $name;
        $this->weapon = new $weapon;
     }
     public function fire($person) {
         $this->weapon->fire($person);
     }
     public function changeWeapon($weapon) {
        $this->weapon = new $weapon;
     }
}

class Sniper extends Fight {   }
class Terrorist extends Fight {   }

class MauserSniper {
     function fire($person) {
         echo "Firing $person->name! Miss! Your rifle is damaged<br />";
     }
}

class AK47 {
     function fire($person) {
         echo "Firing $person->name! Hit with AK47!<br />";
     }
}


class SteyrSSG {
     function fire($person) {
         echo "Firing $person->name! Hit!<br />";
     }
}

$sniper1 = new Sniper("MauserSniper", "Martin");
$sniper2 = new Sniper("SteyrSSG", "Daniel");
$terrorist = new Terrorist("AK47", "Mike");
$sniper1->fire($sniper2); //we'll miss this one.
$sniper1->changeWeapon("SteyrSSG");
$sniper1->fire($sniper2); //hit!
$terrorist->fire($sniper1);

demo

【讨论】:

  • 感谢一个很好的例子,但我仍然不确定 - 如果我不知道“种族”(人类、巨魔等)是什么。但我需要从数据库中提取它,扩展到一个变量,但不起作用:s 我想这更好用,比如 NPC(怪物、老鼠)而不是“用户”本人
  • 非常感谢您迄今为止的帮助!它工作得很好,但我想,我仍在考虑如何扩展更多的东西,例如,如果我有一个“汽车”类,我也想扩展它,但我想我不能扩展多于一堂课?
  • 我认为问题在于我不明白如何扩展“动态”类或类似的东西。这不是它的模式吗?狙击手可以扩展人类,也可以扩展巨魔
  • @John:不,不幸的是你不能。但是你可以在战斗中使用汽车吗?
  • @John:有一些解决方法,但我认为您不需要它。你的想法是什么?
【解决方案2】:

在我这边,我会改用这些类:

Interface iWeapon {}
Interface iAttacker {}
Interface iAttackable {}

Class Human Implements iAttacker, iAttackable {}
Class RangedWeapon Implements iWeapon {}
Class Colt extends RangedWeapon {}
Class M4AA extends RangedWeapon {}
Class Sniper extends RangedWeapon {}
Class Shotgun extends RangedWeapon {}

现在让我解释一下:

iWeapon

描述武器、不同的 getter、setter 和一些动作,例如 DoDamage() 或 GetRandomAttackDamage()。如你所愿。此界面允许您定义武器的基础知识。您可以将此应用于 Weapon 类或派生它的任何其他类,但我会将其保留在至少一个基本类中。该界面的目标是强制所有武器采用相同的行为,它有攻击伤害,射程,也许是收费? (弹药)

iAttacker / iAttackable

描述可以攻击或被攻击的事物。这些接口通常会提供确定攻击能力(是眩晕、固定、禁用?)或被攻击(隐形、无敌?)的功能,并提供攻击其他实现的功能。人类或任何其他生物将实施这些来说,嘿,我可以攻击并被攻击。这个界面还会提供 getter 和 setter 来控制这些生物携带的武器,也许是防止对它们造成伤害的盔甲?

关于界面

请始终记住,类代表的是相对具体的东西。如果您将班级命名为“攻击者”或“目标”,您可能会错过班级的重点。代表有形事物的类和对象。反过来,接口代表类可能采取的动作或角色。他们只指定一个人可以做什么,他们不提供实现本身,他们告诉该对象将实现什么,从而声明他们可以做什么。

希望这会有所帮助:)


关于属性的正确实现是我的建议:

class Player implements iAttacker, iAttackable {
    protected $playerClass;
    protected $race;
    protected $weapon;
    protected $armor;

    public function setClass(playerClass $class){
         $this->playerClass = $class;
    }
    public function getClass(){
         return $this->playerClass;
    }

    public function setRace(race $race){
         $this->race = $race;
    }
    public function getRace(){
         return $this->race;
    }

    public function setWeapon(damagingGear $weapon){
         $this->weapon = $weapon;
    }
    public function getWeapon(){
         return $this->weapon;
    }

    public function setArmor(protectiveGear $armor){
         $this->armor = $armor;
    }
    public function getArmor(){
         return $this->armor;
    }

    public function attack(iAttackable $target){

        //Check we can attack
        if(!$this->canAttack()){ //Check we are not immobilized or disabled
            throw new CannotAttackException($this->getNonAttackingReason());
        }elseif(!$this->weapon->canFire()){
            throw new CannotAttackException($this->weapon->getNonFireableReason());
        }

        //We can attack, roll the damage
        if($target->isAttackable()){
            $target->sufferDamage($this->weapon->rollDamage()+$this->race->getRangedDamageBonus());
        }else{
            thrown new CannotBeAttackedException($target->getNonAttackableReason());
        }
    }

}

【讨论】:

  • “RangedWeapon”应该包含什么? =)
  • 远程武器可以做什么的基本实现,例如界面中描述的内容。那么其他武器可以但不一定会扩展远程武器。在这一点上它的口味问题,你想只有“武器”,“远程武器/近战武器”?这是一个非常大的话题:)
  • 是的,我现在会坚持“远程武器,近战武器”。我在考虑属性,如果我在一个类中声明一个类,是不是意味着,我需要设置我班上的一个方法来执行它? a 类将 var 设置为一个对象,然后在 b 类中设置一个名为 hello() 的方法 现在我需要设置一个“hello”方法,然后像 var->func() 一样放置对吗? (更新了我的问题以显示我的意思)
  • 看看我添加了什么,我花了一些时间才弄明白,但我认为这应该引导你走向我认为正确的方向......
【解决方案3】:

我会避免让 Human 类实现与武器有关的任何东西。实现定义了类必须定义的方法,但不处理类的属性。

对象接口允许您创建代码来指定哪个 类必须实现的方法,而不必定义这些方法是如何实现的 方法被处理。 (PHP Documentation: Object Interfaces)

Class Human {}

Class Sniper extends Human{
 public $weapon
}

Interface Weapons {
  public function fire() 
}

Class Colt implements Weapons {}
Class Bazooka implements Weapons {}

因此,狙击手是人类(但具有 $weapon 属性),而 Colt、Bazooka 等都实现了 Weapons 接口(迫使它们定义一个 fire() 函数。

【讨论】:

  • Class Human {} Class Sniper extends Human{ public $weapon } 我不喜欢这个。我认为 $weapon 是每个人的财产,因此应该属于人类的阶级
  • 可能是这样,并且忽略了这种声明的政治含义:),我正在解决实施问题,而不是财产继承问题。如果你的所有人类都有武器,那么一定要在父类中声明它。
  • 现在我们知道 GTA Vice City 中的“FIGHTFIGHTFIGHT”是做什么的...... =)
猜你喜欢
  • 2018-05-28
  • 2019-03-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-10-07
  • 1970-01-01
相关资源
最近更新 更多