我可以在PHP中使用一个以上的类来扩展一个类吗?

我可以在PHP中使用一个以上的类来扩展一个类吗?,php,class,oop,extends,Php,Class,Oop,Extends,如果我有几个类,它们都有我需要的函数,但我想单独存储以供组织使用,那么我可以扩展一个类来同时拥有这两个函数吗 i、 e.a类扩展b类扩展c类 编辑:我知道如何一次扩展一个类,但我正在寻找一种使用多个基类立即扩展类的方法-好吧,在PHP中你不能这样做,但是应该有一些方法可以绕过它,而不必求助于类c扩展b,类b扩展aPHP还不支持多类继承,但是,它确实支持多接口继承 请参阅以获取一些示例。您不能有一个扩展两个基类的类。你不可能 // this is NOT allowed (for all you

如果我有几个类,它们都有我需要的函数,但我想单独存储以供组织使用,那么我可以扩展一个类来同时拥有这两个函数吗

i、 e.
a类扩展b类扩展c类


编辑:我知道如何一次扩展一个类,但我正在寻找一种使用多个基类立即扩展类的方法-好吧,在PHP中你不能这样做,但是应该有一些方法可以绕过它,而不必求助于
类c扩展b
类b扩展a
PHP还不支持多类继承,但是,它确实支持多接口继承


请参阅以获取一些示例。

您不能有一个扩展两个基类的类。你不可能

// 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

等等。

类并不意味着只是方法的集合。一个类应该表示一个抽象的概念,包括状态(字段)和改变状态的行为(方法)。使用继承只是为了获得一些想要的行为听起来像是糟糕的OO设计,而这正是许多语言不允许多重继承的原因:为了防止“意大利面继承”,即扩展3个类,因为每个类都有一个需要的方法,最后得到一个继承100个方法和20个字段的类,但是只使用了其中的5个。

如果你真的想在PHP5.3中伪造多重继承,你可以使用神奇的函数&uuuu 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”

PHP不允许多重继承,但可以实现多个接口。如果实现“繁重”,则为单独类中的每个接口提供框架实现。然后,您可以通过对象包含将所有接口类委托给这些框架实现

我读过几篇文章,不鼓励在项目中继承(与库/框架相反),鼓励编写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();
    }
}

我相信,很快就会有计划加入混搭

但在那之前,请接受公认的答案。您可以将其抽象一点,以创建一个“可扩展”类:


注意,在这个模型中,“OtherClass”可以“了解”$foo。OtherClass需要一个名为“setExtendee”的公共函数来建立这种关系。然后,如果从$foo调用它的方法,它可以在内部访问$foo。但是,它不会像真正的扩展类那样访问任何私有/受保护的方法/变量。

由于不清楚您想要实现什么,我建议您研究一下重新设计应用程序的可能性,以便在这种情况下使用组合而不是继承。

最好的办法是创建父类,有功能。。。i、 e.将此所有功能添加到父级


并“向下移动”所有使用此层次结构的类。我需要重写特定的函数。

您可以使用traits,希望它可以从PHP5.4中获得

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

它们在支持更好的组合和重用方面的潜力得到了认可,因此它们可以集成到较新版本的语言中,如Perl 6、Squeak、Scala、Slate和Fortress。Traits也被移植到Java和C

更多信息:

我刚刚解决了我的“多重继承”问题:

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中操纵会话,该会话扩展了MyServiceResponsetype,但仍然能够自己处理会话。

如果要检查函数是否为公共函数,请参阅本主题:

并对许多参数或非参数使用call_user_func_数组(…)方法

像这样:

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");
EDIT:2020 PHP5.4+和7+
从PHP5.4.0开始,有“”-您可以在一个类中使用更多的trait,因此最终的决定点将是您是想要真正的继承,还是想要仅仅需要一些“特性”(trait)。Trait,含糊其辞地说,是一个已经实现的接口,它仅仅是
use
d


当前接受的回答是“弗朗克将工作,但事实上它不是多重继承,而是一个在范围内定义的类的子实例,也有一个‘yl调用()”速记——考虑在“扩展”类中需要“外部类类方法”的任何地方使用“$-th->子实例->方法(ARGS)”。 确切答案 不,你不能,分别地,不是真的,正如所说:

扩展类始终依赖于单个基类,即, 不支持多重继承

真实答案 然而,正如@adam正确建议的那样,这并不禁止您使用多层次继承

您可以扩展一个类,用另一个类扩展另一个类,以此类推

关于这一点,非常简单的例子是:

class firstInheritance{}
class secondInheritance extends firstInheritance{}
class someFinalClass extends secondInheritance{}
//...and so on...
重要提示 正如您可能已经注意到的,如果您可以控制流程中包含的所有类,则只能按层次结构执行多(2+)个智能化操作-这意味着您无法应用此解决方案,例如,对于内置类或无法编辑的类-如果您想这样做,剩下的是@frank解决方案-子实例

…最后是一些输出的示例:

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

你可以利用你的性格特征来做到这一点
class firstInheritance{}
class secondInheritance extends firstInheritance{}
class someFinalClass extends secondInheritance{}
//...and so on...
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 
<?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
interface Swift_Transport_IoBuffer extends Swift_InputByteStream, Swift_OutputByteStream
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();
class A {
    //do some things
}

class B {
    //do some things
}
class copy_B extends A {

    //do some things (copy class B)
}

class A_B extends copy_B{}
class C_A extends A{}
class C_B extends B{}
class C_A_b extends A_B{}  //extends A & B