继承在PHP中不起作用

继承在PHP中不起作用,php,class,inheritance,abstract,Php,Class,Inheritance,Abstract,我有这样的结构: abstract class Android { public function __construct() { } public abstract function cost(); public function get_model(){ return "unkown model"; } } class HTC extends Android { public function __construct(

我有这样的结构:

abstract class Android {
    public function __construct() {

    }

    public abstract function cost();

    public function get_model(){
        return "unkown model";
    }
}

class HTC extends Android {

    public function __construct() {
        parent::__construct();
        $this->model= "HTC";
    }

    public function get_model() {
        return $this->model;
    }

    public function cost() {
        return 500;
    }
}

abstract class FeaturesDecorator extends Android {
    public function __construct() {
        parent::__construct();
    }

    public abstract function get_description();
}

class VideoCamera extends FeaturesDecorator {
    private $android;

    public function __construct($android) {
        parent::__construct();
        $this->android=$android;
    }

    public function get_description() {
         return $this->android->get_model()." plus a video camera, ";
    }

    public function cost() {
        return 200 + $this->android->cost();
    }
}

class BigScreenSize extends FeaturesDecorator {
    private $android;

    public function __construct($android) {
        parent::__construct();
        $this->android=$android;
    }

    public function get_description() {
        return $this->android->get_model()." plus a big size screen, ";  
    }

    public function cost() {
        return 100 + $this->android->cost();
    }
}
应用以下模式后:

$android2 = new HTC();
$android2 = new BigScreenSize($android2);
$android2 = new LongLastingBattery($android2);

echo "<br/><br/>You have bought ".$android2->get_description()." for $".$android2->cost();
$android2=新HTC();
$android2=新的大屏幕尺寸($android2);
$android2=新的长效电池($android2);
echo“

您已经用$android2->cost()购买了“$android2->get_description()”;
我明白了

你花650美元买了一个无名品牌加上一个耐用的电池

再次:


我想知道为什么我从
get_model()
调用
get_description()。因此,第一次添加装饰时,
$android2
将是
Android
类型,而不是之前的
HTC

也许你的意思是:

abstract class FeaturesDecorator extends HTC {
  // ...
}
这将为您的示例提供正确的输出


编辑您可以将
模型
成员变量移动到
Android
类;也应该起作用:

abstract class Android {
  protected $model = "unknown model";

  public function get_model() {
    return $this->model;
  }
}
通过这种方式,
模型
直接存储在
Android
中,可以从所有子类中进行设置,并且可以从包含对
Android
对象引用的任何其他类中检索

$android1=new HTC();
$android2=new BigScreenSize($android1);
$android3=new VideoCamera($android2);
在$android2和$android3上执行var_转储将为您提供它们持有的对象(必须更改为videocamera,因为您提供的代码中没有电池类),android3持有的是bigscreensize对象,而不是htc,因此“未知”。如果你想获得你的结果(“HTC”),你必须(首先让$android成为公共的而不是私有的)并且

或者按照你的例子(仍然在课堂上公开$android)

应用这些更改可以让我:

你花了800美元买了HTC plus大屏幕

最后,我仍然保留我最初的想法,即你应该修改你所采取的方法。可能会添加一个方法,从其父级获取$model并在构造函数中使用它。这样可以跟踪模型并使用本地属性。(在上面的示例中,摄像机在执行get_description()时尝试访问bigscreensize->get_model(),此方法在bigscreensize中不存在,但在作为bigscreensize父级的android中存在。继承在这里工作很好。请注意,您的修饰符不知道htc类是否存在,因此除非您为所有修饰符提供一个方法来访问/传递“model”变量。您将无法通过fir访问它st decorator.cost()之所以有效,是因为它存在于每个类中


在昨晚回答之前,我应该先阅读这个问题。对不起。

当我第一次测试你的代码时,php告诉我,类
LongLastingBattery
不存在,这是正确的-它不存在。我想你的意思是
VideoCamera
;所以我回答中的主要功能将从以下内容开始:

$android2 = new HTC();
$android2 = new BigScreenSize($android2);
$android2 = new VideoCamera($android2);
您的问题是,您只是混淆了两个方法
get_description()
get_model()
:首先在摄像机实例上调用get_description()。这里有$this->android->get_model(),其中$this->android是BigScreenSize的实例。BigScreenSize类不会重写方法get_model().BigScreenSize扩展了FeaturesDecorator,它也不重写此方法,但扩展了Android,它有此方法并返回
“未知模型”

为了克服这个问题,您可以在VideoCamera和BigScreenSize中将
$this->android->get_model()
更改为
$this->android->get_description()
,并将android和HTC中的get_model()方法重命名为get_description()。最后,您必须将FeaturesDecorator更改为:

abstract class FeaturesDecorator extends Android {}
然后你会得到这个:

<br/><br/>You have bought HTC plus a big size screen,  plus a video camera,  for $800


您花了800美元购买了HTC plus大屏幕和摄像机
你应该看看这篇博客文章。在这种方法中使用
抽象类
会让PHP不支持多重继承(至少不是这样)。这段代码需要重构,并采取与
抽象类
不同的方法。有什么区别。成本()方法是这样工作的,但是get_description,,,,doesnskiyd。,为什么?@DmitryMakovetskiyd我希望这次我能提供更多的帮助。是的,但是htc有一个Android抽象类,它有get_模型…可以被htc覆盖。@DmitryMakovetskiyd:是的,它可以被
htc
覆盖,但是你的装饰程序没有扩展
htc
——他们只扩展
Android
Android
FeatureDecorator
都不了解
HTC
。您可以做的一件事是将您的
模型
成员变量存储在
Android
中,而不是
HTC
,这样也可以。
abstract class FeaturesDecorator extends Android {}
<br/><br/>You have bought HTC plus a big size screen,  plus a video camera,  for $800