Как deceze уже указывает , это невозможно с наследованием.
Вы можете использовать runkit_class_adopt
в PECL для преобразования базового класса в унаследованный класс, при необходимости добавлять наследственные методы , но runkit - это то, что вы не хотите в вашем производственном коде.
Чистый ОО подход к этому заключался бы в использовании паттерна моста , чтобы дать объекту реализацию класса A во время выполнения и, таким образом,
, отделяющегоабстракция от его реализации, так что они могут варьироваться независимо друг от друга.
Как это работает
Сначала определите интерфейс, который имеет каждый «родитель» B и Bреализовать.Интерфейс должен содержать все методы, которые вы хотите, чтобы B «наследовал».Я помещаю эти термины в кавычки, потому что технически они не являются ни родителями, ни наследуем.
interface MyImplementation
{
public function doSomething();
// more methods …
}
Затем определите классы А1 и А2, реализующие этот интерфейс, и добавьте методы, требуемые интерфейсом.
class A1 implements MyImplementation
{
public function doSomething()
{
return 'A1';
}
// more methods …
}
class A2 implements MyImplementation
{
public function doSomething()
{
return 'A2';
}
// more methods …
}
Затем создайте свой класс B и сделайте так, чтобы при инициализации ему потребовался один из реализующих классов.
abstract class B implements MyImplementation
{
protected $_implementation;
// more properties ...
public function __construct(MyImplementation $implementationObj)
{
$this->_implementation = $implementationObj;
}
public function doSomething()
{
return $this->_implementation->doSomething();
}
// more methods ...
}
Как видите, любые вызовы методов, требуемых нашим интерфейсом, делегируются агрегированному«родительский» объект, поэтому в зависимости от того, что вы передали в B, вы получите разные результаты.
Теперь, чтобы определить C, мы просто заставляем его принять имя класса класса реализации и создать его в C для его передачик родителю, например B.
class C extends B {
public function __construct($bMethodImplementation) {
parent::__construct(new $bMethodImplementation);
}
}
, а затем вы можете сделать
$c = new C('A1');
echo $c->doSomething(); // echoes A1
$c = new C('A2');
echo $c->doSomething(); // echoes A2