Назначить родительский класс классу во время выполнения? - PullRequest
0 голосов
/ 13 ноября 2010

Класс C расширяет B. А класс B расширяет либо A1, либо A2, в зависимости от аргумента конструктора C.Как определить класс A, B и C?

Ответы [ 2 ]

4 голосов
/ 13 ноября 2010

Так как вам нужно жестко закодировать родительский класс (class B extends A1), это невозможно (несмотря на расширения / хаки времени выполнения, которые я бы не рекомендовал использовать). Посмотрите на состав вместо наследования, если вам требуется такая гибкость.

2 голосов
/ 13 ноября 2010

Как 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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...