Настроить подсказку типа в PHP

Я пишу пользовательскую систему расширения для php, которая позволяет определить класс с новой функцией для существующего класса и добавить указанные функции в класс после его определения.

Как уже говорилось, расширения записываются как отдельный класс, давайте назовем один MyExtension и допустим, что это расширение распространяется на существующие классы, MyExtendedClass1 и MyExtendedClass2. Итак, MyExtension добавляет некоторые функции к MyExtendedClass1 И MyExtendedClass2.

Что я хочу сделать, так это позволить пользователям вводить подсказку на основе MyExtension.

// $object is guaranteed to either be an instance of MyExtension
// or be a class that is extended with MyExtension
function someFunction(MyExtension $object) {

}
$post = new MyExtendedClass1(); // Is extended by MyExtension
someFunction($post);

$post = new MyExtendedClass2(); // Is extended by MyExtension
someFunction($post);

Что мне интересно:

Есть ли способ «добавить тип к объекту»? Есть ли способ обмануть проверку типов, чтобы разрешить эти вызовы.


person SomeNorwegianGuy    schedule 20.11.2015    source источник
comment
Разве это уже не работает для вас? Это уже поддерживаемое поведение   -  person castis    schedule 20.11.2015
comment
Вы можете использовать подсказку типа MyExtendedClass, так как все классы MyExtension будут расширять MyExtendedClass. Или, что еще лучше, вы можете создать интерфейс, который должен реализовывать все классы расширения и использовать этот интерфейс для подсказки типа.   -  person akDeveloper    schedule 20.11.2015
comment
В PHP это известно как Подсказка типа. Дополнительную информацию можно найти на веб-сайте PHP: объявления типов   -  person icecub    schedule 20.11.2015
comment
@castis Я говорю не о функции php OOP extends, а скорее о пользовательской системе расширений, которая может добавлять функциональность к классам после того, как они определены   -  person SomeNorwegianGuy    schedule 20.11.2015
comment
@akDeveloper Я отредактировал вопрос, чтобы использовать пример, где это не применимо.   -  person SomeNorwegianGuy    schedule 20.11.2015
comment
@icecub Плохо, исправил.   -  person SomeNorwegianGuy    schedule 20.11.2015
comment
Хорошо, теперь someFunction будет принимать экземпляры класса MyExtension и любой другой экземпляр класса, расширяющий MyExtension. Есть ли причина, по которой вы хотите ввести дочерний класс подсказки, а не родительский класс?   -  person akDeveloper    schedule 20.11.2015
comment
@akDeveloper Прочитайте первую строку, я их отредактировал. Теперь они должны быть яснее. ;)   -  person SomeNorwegianGuy    schedule 21.11.2015


Ответы (1)


Трудно понять ваш вопрос, потому что вам нужно пользовательское расширение, описываемое как объект собственно расширенное.

Если вам нужно, чтобы some_function работала с разными типами, она не может использовать их напрямую, а подсказка типа не может определить конкретный тип — используйте интерфейс.

Ваши типы должны быть расширены за счет функциональности общего интерфейса, от которого может зависеть функция - используйте объекты-оболочки, которые реализуют тот же интерфейс, но знают (как общаться) конкретный тип.

interface MyExtensionInteface {
    public function doSoemthingSpecial();
}

function some_function(MyExtensionInterface $myExtension) {
    $myExtension->doSomethingSpecial();
}

class MyExtensionOfExtendedClass1 implements MyExtensionInteface
{
    public function __construct(MyExtendedClass1 $obj) {
        $this->extended = $obj;
    }

    public function doSomethingSpecial() {
        //...with MyExtendedClass1 type
    }
}

class MyExtensionOfExtendedClass2 impements MyExtensionInterface
{
     public function __construct(MyExtendedClass2 $obj) {
         $this->extended = $obj
     }

     public function doSomethingSpecial() {
         //...with MyExtendedClass2 type
     }
}

$a = new MyExtensionOfExtendedClass1(new MyExtendedClass1());
some_function($a);

$b = new MyExtensionOfExtendedClass2(new MyExtendedClass2());
some_function($b);

Именование «Расширение» предназначено только для контекста вопроса — оно должно иметь реальное значение объекта. Например: DuckSoup(Duck) + ChickenSoup(Chicken) + function:cook(Soup)

person shudder    schedule 21.11.2015