我正在使用Yii2和PHP开发Web应用程序,并面临典型的多重继承情况。
我有类A
和B
扩展Yii2的ActiveRecord
类,因为它们代表存储在数据库中的关系数据。但后来我有C级,它没有(并且不应该)扩展ActiveRecord
但是与A
和B
共享共同的行为和成员变量。换句话说,这三个班级真正共享一个共同的"是一个"与现实世界实体的关系,但只有A
和B
可存储在数据库中。
到目前为止我的工作方式有点使用特征:
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
}
}
然后我有一个方法可以使用三个类中的任何一个(A
,B
或C
)并使用它。到现在为止,我只需要抛出A
或B
,所以我只写了
public fonction someMethod(AbstractMotherClass $entity) {}
所以我可以在IDE中获得类型提示和其他内容。但是现在我必须通过C
并且应用程序崩溃,因为如果我调用AbstractMotherClass
,该方法无法获得预期的someMethod(new C());
实例。要解决这个问题,我需要一个所有A
,B
和C
都可以扩展的公共类,以便我可以在我的方法中键入提示该类。但那将是多重继承,因为A
和B
也必须延伸ActiveRecord
,但C
可以。{/ p>
我发现了很多多重继承问题,但它们都是通过改变对象结构,分担责任,使用组合而不是继承等来解决的。我无法在这里应用这些解决方案,因为它们似乎不合适也不实用,但我可能错了。
最好的方法是什么?
如果有人有更好的标题建议,我很乐意改变它(我找不到好的)。
答案 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。接口通常用于解决一些多重继承问题。