oop — Непоследовательное поведение при переопределении методов с использованием параметров подтипа в переполнении стека

Я обнаружил несоответствие в PHP при переопределении методов в дочерних классах, используя подтипы в качестве параметра для методов. Проще всего объяснить в коде:

interface IngredientInterface {}
interface TomatoInterface extends IngredientInterface {}

class Tomato implements TomatoInterface {}

class Soup {
public function __construct(IngredientInterface $ingredient) {}
public function foo(IngredientInterface $ingredient) {}
}

class TomatoSoup extends Soup {
public function __construct(TomatoInterface $tomato) { parent::__construct($tomato); }
public function foo(TomatoInterface $ingredient) { parent::foo($ingredient); }
}

Можно было бы ожидать, что поведение сообщения об ошибках будет одинаковым для переопределенных методов __construct () и foo (), но это не так.

Метод __construct () не генерирует ошибок в PHP 5.5.38, 5.6.19 и 7.0.4

Метод foo () генерирует следующую ошибку в 5.5.38 и 5.6.19:

Strict Standards: Declaration of TomatoSoup::foo() should be compatible with Soup::foo(IngredientInterface $ingredient) in H:\webroot\test.php on line 16

и в 7.0.4:

Warning: Declaration of TomatoSoup::foo(TomatoInterface $ingredient) should be compatible with Soup::foo(IngredientInterface $ingredient) in H:\webroot\test.php on line 16

Теперь я не обеспокоен тем, что тип ошибки изменился с E_STRICT на E_WARNING, меня больше беспокоит несогласованность штрафа синтаксического анализа конструктора, но метод foo () — нет.

Это ошибка в PHP? Должен ли я сообщить об этом на bugs.php.net?

1

Решение

Зачем вам нужен подтип, если вы расширяете класс, если у вас есть супертип IngredientInterface, вы можете передать каждый объект, который является подтипом IngredienteInterface, конструктору и методу foo (помните хорошие практики Лискова принцип замещения), и, ¿почему вы хотите расширить интерфейс? (помните принцип разделения интерфейса)

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

<?php

interface IngredientInterface {}
interface TomatoInterface extends IngredientInterface {}

class Ingredient implements IngredientInterface {}
class Tomato implements TomatoInterface {}

class Soup {
public function __construct(IngredientInterface $ingredient) {}
public function foo(IngredientInterface $ingredient) {}
}

class TomatoSoup extends Soup {
public function __construct(IngredientInterface $tomato) { parent::__construct($tomato); }
public function foo(IngredientInterface $ingredient) { parent::foo($ingredient); }
}

$tom = new TomatoSoup(new Tomato());
$tom->foo(new Tomato());

$tom2 = new TomatoSoup(new Ingredient());
$tom2->foo(new Ingredient());
0

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]