在没有组合的情况下在PHP中解决多重继承

时间:2018-04-18 19:49:34

标签: php structure multiple-inheritance composition

我正在使用Yii2和PHP开发Web应用程序,并面临典型的多重继承情况。

我有类AB扩展Yii2的ActiveRecord类,因为它们代表存储在数据库中的关系数据。但后来我有C级,它没有(并且不应该)扩展ActiveRecord但是与AB共享共同的行为和成员变量。换句话说,这三个班级真正共享一个共同的"是一个"与现实世界实体的关系,但只有AB可存储在数据库中。

到目前为止我的工作方式有点使用特征:

abstract class AbstractMotherClass extends ActiveRecord {
    use MyTrait;
}

class A extends AbstractMotherClass {}

class B extends AbstractMotherClass {}

class C {
    use MyTrait;
}

trait MyTrait {
    public $someVariableInherentToAllThreeClasses;

    public function someMethodInherentToAllThreeClasses() {
        // do something
    }
}

然后我有一个方法可以使用三个类中的任何一个(ABC)并使用它。到现在为止,我只需要抛出AB,所以我只写了

public fonction someMethod(AbstractMotherClass $entity) {}

所以我可以在IDE中获得类型提示和其他内容。但是现在我必须通过C并且应用程序崩溃,因为如果我调用AbstractMotherClass,该方法无法获得预期的someMethod(new C());实例。要解决这个问题,我需要一个所有ABC都可以扩展的公共类,以便我可以在我的方法中键入提示该类。但那将是多重继承,因为AB也必须延伸ActiveRecord,但C可以。{/ p>

我发现了很多多重继承问题,但它们都是通过改变对象结构,分担责任,使用组合而不是继承等来解决的。我无法在这里应用这些解决方案,因为它们似乎不合适也不实用,但我可能错了。

最好的方法是什么?

如果有人有更好的标题建议,我很乐意改变它(我找不到好的)。

1 个答案:

答案 0 :(得分:1)

正如Greg Schmidt所提到的,你可以使用接口

class ActiveRecord {

}

interface SameInterface {
    public function someMethodInherentToAllThreeClasses();
}

abstract class AbstractMotherClass extends ActiveRecord implements SameInterface{
    use MyTrait;
}

class A extends AbstractMotherClass {}

class B extends AbstractMotherClass {}

class C implements SameInterface{
    use MyTrait;
}

trait MyTrait {
    public $someVariableInherentToAllThreeClasses;

    public function someMethodInherentToAllThreeClasses() {
        return 'bar';
    }
}

function foo(SameInterface $o) {
    return $o->someMethodInherentToAllThreeClasses().PHP_EOL;
}

echo foo(new C());

当然,您必须在界面中复制粘贴someMethodInherentToAllThreeClasses。接口通常用于解决一些多重继承问题。