继承在PHP
我有这样的结构:继承在PHP
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();
我得到
你买未知的品牌加上一个长只要$ 650
还是那句话:
我不知道为什么我得到Unknown brand
而不是HTC
从get_model()
通过get_description()
叫,而$650
被正确计算。
您的FeatureDecorator
继承自Android
,而不是从HTC
继承。因此,第一次添加装饰时,$android2
将是Android
而不是以前的HTC
类型。
也许你的意思如下:
abstract class FeaturesDecorator extends HTC {
// ...
}
这应该给你的例子正确的输出。
编辑则可以将model
成员变量移动到Android
类;应该工作以及:
abstract class Android {
protected $model = "unknown model";
public function get_model() {
return $this->model;
}
}
这样model
直接存储内Android
,可以从所有的子类进行设置,可以从持有到Android
对象的引用任何其他类进行检索。
是的,但HTC获得了Android抽象类,其中有get_model ...可以被htc重写.. – 2012-07-17 04:59:09
@DmitryMakovetskiyd:是的,它可以被'HTC'重写,但是你的装饰者不会扩展'HTC' - 他们只扩展'Android'。 “Android”和“FeatureDecorator”都不知道“HTC”。你可以做的一件事是将'model'成员变量存储在'Android'而不是'HTC'中,这也可以起作用。 – knittl 2012-07-17 08:30:44
$android1=new HTC();
$android2=new BigScreenSize($android1);
$android3=new VideoCamera($android2);
上做$ android2和3会给你他们持有的对象的var_dump(不得不改变,以摄影机为电池类中不存在您提供的代码)和android3持有bigscreensize对象不是HTC ,因此是'未知'。如果你想获得你的结果(以下简称“HTC”),你必须(让$ Android的市民,不要私第一)和
echo $android3->android->get_description();
或根据你的榜样(仍然在你的班级做$安卓公众)
echo $android2->android->get_description();
应用这些变化给我:
你买HTC加上大尺寸屏幕,为$ 800
最后我仍然认为你应该修补你所采取的方法。也许添加一个方法,它可以从它的父级获得$模型,并在构造函数中使用它。这样您可以跟踪模型并使用本地属性。(在我上面的例子中,videocamera尝试在执行get_description()时访问bigscreensize-> get_model(),这个方法在bigscreensize中不存在,但是在android中是bigscreensize的父类的父类。装饰器不知道htc类的存在,所以除非你提供了一个方法让所有的装饰器访问/传递'model'变量,你将无法访问它传递的第一个装饰器。在
每节课我应该读的问题之前,我昨晚回答对不起
最新的区别。 cost()方法是这样工作的,但是get_description ,,, does not..why? – 2012-07-17 04:58:11
@DmitryMakovetskiyd我希望这次能有更多的帮助。 – StrayObject 2012-07-17 09:21:49
当我第一次测试你的代码,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,它具有此方法并返回"unknown model"
。
为了克服这个问题,你可以在这两个摄影机和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
LongLastingBattery类? – LanguagesNamedAfterCofee 2012-07-16 19:53:53
您应该查看[this](http://blog.ircmaxell.com/2012/07/oop-vs-procedural-code.html)博客文章。在这种方法中使用'abstract class'使得它在PHP中不支持多重继承(至少不是这种方式)。这段代码需要重构,并采取与“抽象类”不同的方法。 – Whisperity 2012-07-16 20:11:50
hmmm ..感谢文章 – 2012-07-17 05:03:22