如果我有几个具有所需功能但要为组织单独存储的功能的课程,我可以扩展一堂课吗?

IE class a extends b extends c

编辑:我知道如何一次扩展一类,但是我正在寻找一种使用多个基类立即扩展类的方法 - AFAIK您不能在PHP中执行此操作 class c extends b, class b extends a

有帮助吗?

解决方案

回答您的编辑:

如果您真的想伪造多重继承,则可以使用魔术函数__call()。

尽管从A类用户的角度来看,这还是丑陋的:

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提供。

特征是单个继承语言(例如PHP)的代码重复使用的机制。特征旨在通过使开发人员能够在生活在不同类别层次结构中的几个独立类中自由重复使用方法来减少单个继承的某些局限性。特征和类的组合的语义是通过一种方式定义的,从而降低了复杂性并避免了与多种继承和混合蛋白相关的典型问题。

他们因支持更好的构图和重复利用而获得认可,因此将其集成到诸如Perl 6,Squeak,Scala,Scala,Slate和Fortress之类的新版本中。特征也已移植到Java和C#。

更多信息: https://wiki.php.net/rfc/traits

课程不仅仅是方法的集合。一个类应该代表一个抽象概念,其状态(字段)和行为(方法)都会改变状态。使用继承只是为了获得一些理想的行为听起来像是错误的OO设计,而确切的原因是许多语言都禁止多重继承的原因:为了防止“意大利面条继承”,即延长了3个类,因为每个类都有您需要的方法,并且最终得到了。一个继承100种方法和20个字段的类,但只使用了其中的5个字段。

我相信,有计划很快添加混合件。

但是在那之前,请选择接受的答案。您可以将其提取一点以使“可扩展”类:

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();

请注意,在此模型中,“其他班级”将“知道” $ foo。其他班级需要具有称为“ setextendee”的公共功能来设置这种关系。然后,如果它的方法是从$ foo调用的,则可以在内部访问$ foo。但是,它将无法像真正的扩展类那样访问任何私有/受保护的方法/变量。

@franck当前接受的答案将起作用,但实际上不是多个继承,而是按范围定义的子类实例,也有 __call() 速记 - 考虑仅使用 $this->childInstance->method(args) 在“扩展”类中需要外部频道类方法的任何地方。

确切的答案

不,您分别不能,不是真的 手册 extends 关键词 说:

扩展类始终取决于单个基类,也就是说,不支持多个继承。

真正的答案

但是,正如@adam正确建议的那样,这并不禁止您使用多个层次结构继承。

您可以与另一个类别一起扩展一个班级,而另一个类也可以延长...

如此简单的例子就是:

class firstInheritance{}
class secondInheritance extends firstInheritance{}
class someFinalClass extends secondInheritance{}
//...and so on...

重要的提示

您可能已经注意到, 如果您对流程中包含的所有类别有控制权,则只能通过层次结构进行多个(2+)的整体 - 这意味着,您不能应用此解决方案,例如内置类别或无法编辑的类,如果您想这样做,则剩下@franck解决方案 - 儿童实例。

...最后一个输出的示例:

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 A 
I am b of B 
I am c of C 

使用特征作为基础类。然后在父级中使用它们。扩展它。

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();

看到现在的女商人在逻辑上继承了商业和人类。

<?php
// what if we want to extend more than 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("Mahdi");
$o->setCountry("Al-Ahwaz");
echo $o;
?>

我读了几篇文章,劝阻项目中的继承(而不是库/框架),并鼓励对Agaisnt接口进行编程,而没有反对实施。
他们还通过构图提倡OO:如果您需要A类和B中的功能,则使C具有此类成员/字段:

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();
    }
}

多个继承似乎在接口级别起作用。我对PHP 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

我还没有玩它,但是我认为分享可能很有趣。

我只是解决了我的“多继承”问题:

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;
    }

}

这样,我就可以在会话中操纵会话的能力,该会话扩展了MyServicerSponsype,仍然能够单独处理会话。

您可以使用PHP中宣布为5.4的PHP中的特征来做到这一点

这是您的快速教程, http://culttt.com/2014/06/25/php-traits/

PHP尚未支持多个类继承,但是它确实支持多个接口继承。

http://www.hudzilla.org/php/6_17_0.php 有关一些例子。

PHP不允许多个继承,但是您可以实现多个接口。如果实施“重”,请提供 骨骼实现 对于单独的类中的每个接口。那么你也能 将所有接口类委派给这些骨骼实现 通过 对象遏制.

我不知道您要实现的目标,我建议您研究重新设计应用程序以使用构图而不是继承的可能性。

总是好主意是将父级和函数置于函数...即将所有功能添加到父母中。

并“移动”所有在层次上使用此类别的类。我需要 - 重写功能,这是特定的。

如果要检查功能是否公开,请参阅此主题: 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作为编程语言的问题之一是您只能拥有单一的继承。这意味着一个类只能从另一个类继承。

但是,很多时候从多个类中继承将是有益的。例如,可能希望从几个不同类中继承方法以防止代码重复。

这个问题可能会导致班级具有悠久的继承历史,而这通常是没有意义的。

在PHP 5.4中,该语言的新功能被称为特征。特征就像混合蛋白一样,它使您可以将特征类混合到现有类中。这意味着您可以减少代码重复并获得好处,同时避免多元继承问题。

特质

A类扩展B {}

B类扩展C {}

然后A均扩展了B和C

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top