Как я могу переписать функцию php, у которой установлена ​​подсказка типа аргумента? - PullRequest
3 голосов
/ 09 апреля 2019

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

Подробнее о том, что я пытаюсь сделать на https://laracasts.com/discuss/channels/general-discussion/type-hint-hell

Я пытался изменить код для использования интерфейсов и аннотаций,но я не могу предотвратить ошибку "Declaration of class .... must be compatible with".

Это то, что я пытаюсь сделать в двух словах.

Пакет имеет такой тип установки.

class ClassA {}

class ClassB {
    public function makeClassA(ClassA $classA) : ClassA
    {
        return $classA;
    }
}

Это то, что я пытаюсь сделать.

class ClassANew {}

class ClassC extends ClassB {
    public function makeClassA(ClassANew $classA) : ClassANew
    {
        return $classA;
    }
}

Я получаю следующую ошибку,

"Неустранимая ошибка PHP: Объявление ClassC :: makeClassA (ClassANew$ classA): ClassANew должен быть совместим с ClassB :: makeClassA (ClassA $ classA): ClassA "

Я знаю, что могу просто разветвить код и удалить заблокированный classA из ClassB, но я пытался этого не делать.

Если я собирался раскошелиться на код, я посмотрел, как сохранить исходную предпосылку исходного кода.Итак, я попытался изменить ClassA ссылки в ClassB на ClassAInterface, но я получаю ту же ошибку.

Возможно ли то, что я пытаюсь сделать?

Ответы [ 3 ]

3 голосов
/ 09 апреля 2019
0 голосов
/ 10 апреля 2019

Хорошо, так что я наконец-то понял проблему. Я должен был сохранить исходные ссылочные типы возвращаемых данных одинаковыми. После этого все работает нормально.

namespace Original;

class ClassExtra {}

class ClassA {
    public function __construct($container, ClassB $classB) {}
}

class ClassB {
    public function __construct(ClassExtra $classExtra) {}
}

class ClassC {
    public $classB;
    public $containers;
    public function __construct(ClassB $classB) {
        $this->classB = $classB;
    }
    public function container(string $container = 'default'): ClassA
    {
        $this->containers[$container] = new ClassA($container, $this->classB);
        return $this->containers[$container];
    }
}

Namespace Changes;

Class NewClassA extends \Original\ClassA {}
Class NewClassB extends \Original\ClassB {}
Class NewClassC extends \Original\ClassC {
    public function container(string $container = 'default'): \Original\ClassA
    {
        $this->containers[$container] = new NewClassA($container, $this->classB);
        return $this->containers[$container];
    }
}

$classC = new \Original\ClassC(new \Original\ClassB(new \Original\ClassExtra()));
var_dump(get_class($classC->container('test')));
/* string(15) "Original\ClassA" */

$classC = new NewClassC(new NewClassB(new \Original\ClassExtra()));
var_dump(get_class($classC->container('test')));
/* string(17) "Changes\NewClassA" */
0 голосов
/ 09 апреля 2019

это небольшой трюк, но его особенность, которая не вызывает проблем с безопасностью , в прошлом или уже использованных и проверенных.

Я знаю, что это не то, что вам нужноно это решает вашу проблему в полной мере, сохраняя при этом безопасность и форсирование возвратов методов

class ClassA {}

class ClassB {
    public function makeClassA_ClassB(ClassA $classA) : ClassA
    {
        return $classA;
    }
    function __call($function_name, $argument){
        if ($function_name==="makeClassA" && $argument[0] instanceof ClassA ) return $this->makeClassA_ClassB($argument[0]);
    }
}
class ClassANew {}

class ClassC extends ClassB {
    public function makeClassA_ClassC(ClassANew $classA) : ClassANew
    {
        return $classA;
    }
    function __call($function_name, $argument){
        if ($function_name==="makeClassA" && $argument[0] instanceof ClassANew ) return $this->makeClassA_ClassC($argument[0]);
    }
}

$t=new ClassC();
$t2=new ClassANew();
var_dump($t->makeClassA($t2)); // object(ClassANew)#212 (0) { }

$t=new ClassB();
$t2=new ClassA();
var_dump($t->makeClassA($t2)); // object(ClassA)#212 (0) { }
...