【发布时间】:2014-02-09 22:16:11
【问题描述】:
我有以下 OOP 结构:
<?php
interface AnimalInterface
{
public function getName();
}
class Dog implements AnimalInterface
{
public function getName() {
return 'dog';
}
public function makeFriends()
{
echo 'I have friends now :)';
}
}
class Cat implements AnimalInterface
{
public function getName() {
return 'cat';
}
public function hateFriends()
{
echo 'I cant make friends :(';
}
}
interface AnimalDoInterface
{
public function makeFriend(AnimalInterface $animal);
}
class DogFriend implements AnimalDoInterface
{
public function makeFriend(Dog $dog)
{
$dog->makeFriends();
}
}
class CatFriend implements AnimalDoInterface
{
public function makeFriend(Cat $cat)
{
$cat->hateFriends();
}
}
现在Object Interfaces 上的 PHP 手册说:
实现接口的类必须使用与接口中定义的完全相同的方法签名。不这样做会导致致命错误。
为什么会这样?我完全误解了接口吗?当然,我应该能够使用任何接口或该接口的实现来声明AnimalDoInterface::makeFriend?在这种情况下,它在技术上应该是兼容的,因为 Cat 实现了 AnimalInterface,这是它所期望的。
不管我的 OOP 是否出错,有没有办法在 PHP 中实现它?
所以看来我不够清楚,我的错。但是,基本上我想要实现的是让AnimalDoInterface 的实现比它的接口说的更严格。所以在这种情况下,我希望DogFriend::makeFriend 只允许Dog 类作为它的参数,在我看来这应该是可以接受的,因为它实现了AnimalInterface,而CatFriend 允许Cat类,这又是一回事。
编辑:修复了类,还添加了我想要实现的目标。
编辑 2:
所以目前,我必须实现它的方式如下:
class DogFriend implements AnimalDoInterface
{
public function makeFriend(AnimalInterface $dog)
{
if(!($dog instanceof Dog)) {
throw new \Exception('$dog must be of Dog type');
}
$dog->makeFriends();
}
}
class CatFriend implements AnimalDoInterface
{
public function makeFriend(AnimalInterface $cat)
{
if(!($dog instanceof Cat)) {
throw new \Exception('$dog must be of Cat type');
}
$cat->hateFriends();
}
}
我希望避免对类类型进行这种额外检查。
【问题讨论】:
-
我不认为我在关注你所说的任何事情。实际问题是什么? “方法签名”是指方法名称、参数(带有类型提示)、可见性(公共/私有)以及它是否是静态的。
-
不完全清楚你在问什么。您是否尝试运行上面的代码?
Fatal error: Class Dog contains 1 abstract method and must therefore be declared abstract or implement the remaining methods (AnimalInterface::getAnimalName)会出错 -
实现的
AnimalInterface类没有抽象的方法getAnimalName()。并且必须使用。请记住,所有接口方法本身都是抽象的,必须在类中实现 -
接口是一种契约,保证将使用实现该接口的类的实例的任何人实现一组具有特定签名的方法。如果您需要两组功能,而不是在您的类之间共享,则将签名分隔在两个单独的接口中。
-
我的错,修复了 PHP 以转到正确的错误,而不是 @MichaelBerkowski 所说的。