我在使用子类型作为方法的参数时,在子类中重写方法时发现了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吗?
答案 0 :(得分:0)
如果你要扩展一个类,为什么你想拥有一个子类型,如果你有一个超类型IngredientInterface你可以将每个对象是IngredienteInterface的子类型传递给构造函数和方法foo(记住好的做法Liskov替换原则),¿为什么要扩展接口? (记住界面隔离原则)
如果您在子类中使用超类型,结果是一样的,但我认为您必须再查看一下您的代码,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());