我可以使用PHP中的多个类来扩展一个类吗?
如果我有几个function需要但是要分开存放的组织,我可以扩展一个类来兼有吗?
即class a extends b extends c
编辑:我知道如何一次扩展一个类,但我正在寻找一种方法来即时扩展一个类使用多个基类 – AFAIK你不能这样做在PHP中,但应该有办法解决它,而不诉诸class c extends b
, class b extends a
回答你的编辑:
如果你真的想伪造多重inheritance,你可以使用魔术函数__call()。
从A级用户的angular度来看,这很丑陋:
class B { public function method_from_b($s) { echo $s; } } class C { public function method_from_c($s) { echo $s; } } class A extends B { private $c; public function __construct() { $this->c = new C; } // fake "extends C" using magic function public function __call($method, $args) { $this->c->$method($args[0]); } } $a = new A; $a->method_from_b("abc"); $a->method_from_c("def");
打印“abcdef”
你不能有一个扩展两个基类的类。 你不能有。
// this is NOT allowed (for all you google speeders) Matron extends Nurse, HumanEntity
你可以有一个层次如下…
Matron extends Nurse Consultant extends Doctor Nurse extends HumanEntity Doctor extends HumanEntity HumanEntity extends DatabaseTable DatabaseTable extends AbstractTable
等等。
你可以使用特性,希望可以从PHP 5.4中获得。
特性是单一inheritance语言(如PHP)中的代码重用机制。 特质旨在通过使开发人员能够在生活在不同类层次结构中的几个独立类中自由地重用一组方法,从而减less单一inheritance的某些限制。 Traits和类的组合的语义是以一种方式定义的,这样降低了复杂性,避免了与多重inheritance和Mixin相关的典型问题。
他们被认为是支持更好的组合和重用的潜力,因此它们被集成到Perl 6,Squeak,Scala,Slate和Fortress等新语言中。 特质也被移植到Java和C#。
更多信息: https : //wiki.php.net/rfc/traits
类并不意味着只是方法的集合。 一个类应该表示一个抽象的概念,用状态(字段)和行为(方法)来改变状态。 使用inheritance只是为了得到一些期望的行为听起来像糟糕的OOdevise,正是许多语言不允许多重inheritance的原因:为了防止“意大利面inheritance”,即扩展3个类,因为每个类都有一个你需要的方法,最后一个inheritance100个方法和20个字段的类,但只使用了5个。
我相信很快就有计划join混合。
但在此之前,请按照接受的答案行事。 你可以抽象出一个“扩展”类:
class Extendable{ private $extender=array(); public function addExtender(Extender $obj){ $this->extenders[] = $obj; $obj->setExtendee($this); } public function __call($name, $params){ foreach($this->extenders as $extender){ //do reflection to see if extender has this method with this argument count if (method_exists($extender, $name)){ return call_user_func_array(array($extender, $name), $params); } } } } $foo = new Extendable(); $foo->addExtender(new OtherClass()); $foo->other_class_method();
请注意,在这个模型中,“OtherClass”得到关于$ foo的“知道”。 OtherClass需要有一个名为“setExtendee”的公共函数来build立这种关系。 然后,如果方法是从$ foo调用的,它可以在内部访问$ foo。 但是,它不会像真正的扩展类那样访问任何私有/受保护的方法/variables。
我读过几篇文章,不鼓励项目中的inheritance(相对于库/框架),并且鼓励对agaisnt接口进行编程,而不是针对实现。
他们还主张OO的构成:如果你需要a和b类的function,使c有这种types的成员/领域:
class C { private $a, $b; public function __construct($x, $y) { $this->a = new A(42, $x); $this->b = new B($y); } protected function DoSomething() { $this->a->Act(); $this->b->Do(); } }
目前被@Franck接受的答案是可行的,但实际上并不是多重inheritance,而是一个定义在范围外的类的子实例,也有__call()
速记 – 考虑使用$this->childInstance->method(args)
在“扩展”类中任何需要ExternalClass类方法的地方。
确切的答案
不,你不能,分别不是真的,因为手册的extends
关键字说:
扩展类总是依赖于一个基类,也就是说,不支持多inheritance。
真正的答案
然而,正如@adambuild议正确,这不禁止您使用多层次inheritance。
你可以扩展一个类,另一个和另一个类,等等…
所以很简单的例子就是:
class firstInheritance{} class secondInheritance extends firstInheritance{} class someFinalClass extends secondInheritance{} //...and so on...
重要的提示
正如你可能已经注意到的那样, 如果你可以控制进程中包含的所有类,那么你只能通过层次结构来执行多个(2+)的intehritance – 也就是说,你不能应用这个解决scheme,比如内置的类或者类根本无法编辑 – 如果你想这样做,你剩下的@Franck解决scheme – 子实例。
…最后是一些输出的例子:
class A{ function a_hi(){ echo "I am a of A".PHP_EOL."<br>".PHP_EOL; } } class B extends A{ function b_hi(){ echo "I am b of B".PHP_EOL."<br>".PHP_EOL; } } class C extends B{ function c_hi(){ echo "I am c of C".PHP_EOL."<br>".PHP_EOL; } } $myTestInstance = new C(); $myTestInstance->a_hi(); $myTestInstance->b_hi(); $myTestInstance->c_hi();
哪个输出
I am a of AI am b of BI am c of C
<?php // what if we want to extend more then one class? Abstract class ExtensionBridge { // array containing all the extended classes private $_exts = array(); public $_this; function __construct(){$_this = $this;} public function addExt($object) { $this->_exts[]=$object; } public function __get($varname) { foreach($this->_exts as $ext) { if(property_exists($ext,$varname)) return $ext->$varname; } } public function __call($method,$args) { foreach($this->_exts as $ext) { if(method_exists($ext,$method)) return call_user_method_array($method,$ext,$args); } throw new Exception("This Method {$method} doesn't exists"); } } class Ext1{ private $name=""; private $id=""; public function setID($id){$this->id = $id;} public function setName($name){$this->name = $name;} public function getID(){return $this->id;} public function getName(){return $this->name;} } class Ext2{ private $address=""; private $country=""; public function setAddress($address){$this->address = $address;} public function setCountry($country){$this->country = $country;} public function getAddress(){return $this->address;} public function getCountry(){return $this->country;} } class Extender extends ExtensionBridge { function __construct() { parent::addExt(new Ext1()); parent::addExt(new Ext2()); } public function __toString() { return $this->getName().', from: '.$this->getCountry(); } } $o = new Extender(); $o->setName("fabio"); $o->setCountry("brazil"); echo $o; ?>
我刚刚解决了我的“多重inheritance”问题:
class Session { public $username; } class MyServiceResponsetype { protected $only_avaliable_in_response; } class SessionResponse extends MyServiceResponsetype { /** has shared $only_avaliable_in_response */ public $session; public function __construct(Session $session) { $this->session = $session; } }
通过这种方式,我有权操纵SessionResponse中的Session,该SessionResponse扩展了MyServiceResponsetype,它仍然能够自己处理Session。
您可以使用PHP中的特性来实现这个function
这里有一个快速教程, http://culttt.com/2014/06/25/php-traits/
多重inheritance似乎在界面级别上工作。 我做了一个testingPHP 5.6.1。
这是一个工作代码:
<?php interface Animal { public function sayHello(); } interface HairyThing { public function plush(); } interface Dog extends Animal, HairyThing { public function bark(); } class Puppy implements Dog { public function bark() { echo "ouaf"; } public function sayHello() { echo "hello"; } public function plush() { echo "plush"; } } echo PHP_VERSION; // 5.6.1 $o = new Puppy(); $o->bark(); $o->plush(); $o->sayHello(); // displays: 5.6.16ouafplushhello
我不认为这是可能的,但我偶然发现了SwiftMailer源代码中的Swift_Transport_IoBuffer类,它具有以下定义:
interface Swift_Transport_IoBuffer extends Swift_InputByteStream, Swift_OutputByteStream
我还没有玩,但我认为这可能是有趣的分享。
PHP尚不支持多类inheritance,但它支持多接口inheritance。
有关示例,请参阅http://www.hudzilla.org/php/6_17_0.php 。
PHP不允许多重inheritance,但可以通过实现多个接口来完成。 如果实现“重”,则为每个独立类中的接口提供骨架实现 。 然后,可以通过对象包含 将所有接口类委托给这些骨架实现 。
不知道你想要达到什么目的,我会build议寻找在这种情况下重新devise你的应用程序使用组合而不是inheritance的可能性。
总是好主意是做父母类,与function…即增加这个所有function对父母。
和“移动”所有使用这个分层次的类。 我需要 – 重写函数,这是特定的。
如果您想检查一个函数是否公开,请参阅以下主题: https : //stackoverflow.com/a/4160928/2226755
并且使用call_user_func_array(…)方法来处理很多或者没有参数。
喜欢这个 :
class B { public function method_from_b($s) { echo $s; } } class C { public function method_from_c($l, $l1, $l2) { echo $l.$l1.$l2; } } class A extends B { private $c; public function __construct() { $this->c = new C; } public function __call($method, $args) { if (method_exists($this->c, $method)) { $reflection = new ReflectionMethod($this->c, $method); if (!$reflection->isPublic()) { throw new RuntimeException("Call to not public method ".get_class($this)."::$method()"); } return call_user_func_array(array($this->c, $method), $args); } else { throw new RuntimeException("Call to undefined method ".get_class($this)."::$method()"); } } } $a = new A; $a->method_from_b("abc"); $a->method_from_c("d", "e", "f");
PHP作为一种编程语言的问题之一是你只能有单一的inheritance。 这意味着一个类只能从另一个类inheritance。
但是,很多时候从多个类inheritance是有益的。 例如,为了防止代码重复,可能需要inheritance几个不同类的方法。
这个问题可能会导致class级有一个长期的遗传家族的历史往往是没有意义的。
在PHP 5.4中,该语言的一个新特性被称为Traits。 Trait有点像Mixin,它允许你将Trait类混合到一个已经存在的类中。 这意味着您可以减less代码重复并获得好处,同时避免多重inheritance的问题。
性状
使用特质作为基类。 然后在父类中使用它们。 扩展它。
trait business{ function sell(){ } function buy(){ } function collectMoney(){ } } trait human{ function think(){ } function speak(){ } } class BusinessPerson{ use business; use human; // If you have more traits bring more } class BusinessWoman extends BusinessPerson{ function getPregnant(){ } } $bw = new BusinessWoman(); $bw ->speak(); $bw->getPregnant();
看现在的女商人逻辑上inheritance的事业和人两者;