如果类在这样的文件中,则看起来不会发生严格错误:
abstract class Food{}
class Meat extends Food{}
abstract class Animal{
function feed(Food $food){ }
}
class Cat extends Animal{
function feed(Meat $meat){
parent::feed($meat);
}
}
但是如果你把类定义放在单独的文件中并包含它们:
abstract class Food{}
class Meat extends Food{}
require 'Animal.php';
require 'Cat.php';
抛出严格的标准错误消息:
严格标准:
Cat::feed()
声明应与c:\ path \ to \ Cat.php中的Animal::feed(Food $food)
兼容...
如果所有文件都在一个文件中,即使这样也可以:
class Dog extends Animal{
function feed($qty = 1){
for($i = 0; $i < $qty; $i++){
$Meat = new Meat();
parent::feed($Meat);
}
}
}
这是预期的行为吗?
因为Meat
是Food
,所以首先不应该抱怨,对吧?
所以解决方案很简单明了:将所有内容放在一个文件中,并且满足严格的标准;)
任何提示赞赏
答案 0 :(得分:3)
这是预期的行为吗?
不幸的是,是的。与类声明相关的复杂性使得当它们全部出现在同一个脚本中时,并不总是应用严格的规则;每个文件的单个类不会出现此问题。
因为肉是一种食物,所以不应该首先抱怨,对吧?
错误有两个原因:
答案 1 :(得分:1)
PHP
在类和名称空间方面的许多奇怪行为之一。
标准解决方案是创建Interface
(让我们将其命名为FoodInterface') and implement it in the base class. Then use
FoodInterface as the type of the argument of method
feed()`:
interface FoodInterface {}
abstract class Food implements FoodInterface {}
class Meat extends Food {}
abstract class Animal {
function feed(FoodInterface $food) {}
}
class Cat extends Animal {
function feed(FoodInterface $meat) {
parent::feed($meat);
}
}
FoodInterface
界面可以为空,或者您可以在其中声明需要在Animal::feed()
中调用的功能。
通过这种方式,您feed()
Cat
(或任何其他Animal
)可以使用任何实现FoodInterface
的对象,无论它们是否扩展Food
或不是。只要他们实现了界面,就可以将它们提供给任何Animal
。
class Toy implements FoodInterface {}
$cat = new Cat();
$cat->feed(new Toy()); // He can't eat it but at least he will have some fun :-)
因为您的基类是抽象的,所以它可以充当前面提到的接口。忘记界面,只需使用与Cat::feed()
相同的参数类型声明Animal::feed()
。
然后,在Cat::feed()
的实现中,您可以使用instanceof
来检查所接收参数的类型是否是您想要的类型(Meat
):
abstract class Food {}
class Meat extends Food {}
abstract class Animal {
function feed(Food $food) {}
}
class Cat extends Animal {
function feed(Food $meat) {
if (! $meat instanceof Meat) {
throw new InvalidArgumentException("Cats don't eat any Food. Meat is required");
}
// Here you are sure the type of $meat is Meat
// and you can safely invoke any method of class Meat
parent::feed($meat);
}
}
第一种方法是正确的方法。第二种方法有其自身的优点,我建议仅在第一种方法由于某种原因不可能时才使用它。