我认为php的OOP实现存在问题。
编辑:考虑更多说明性示例:
abstract class Animal {
public $name;
// public function Communicate(Animal $partner) {} // Works
public abstract function Communicate(Animal $partner); // Gives error
}
class Panda extends Animal {
public function Communicate(Panda $partner) {
echo "Hi {$partner->name} I'm a Panda";
}
}
class Human extends Animal {
public function Communicate(Human $partner) {
echo "Hi {$partner->name} I'm a Human";
}
}
$john = new Human(); $john->name = 'John';
$mary = new Human(); $mary->name = 'Mary';
$john->Communicate($mary); // should be ok
$zuzi = new Panda(); $zuzi->name = 'Zuzi';
$zuzi->Communicate($john); // should give error
问题是当Animal :: Communicate是一个抽象方法时,php告诉以下方法是非法的:
“公共功能沟通(熊猫$伙伴)” “公共职能沟通(人力资源合作伙伴)”
但是当Animal :: Communicate是非抽象的但是没有实现时,Php认为这些方法是合法的。所以在我看来这是不对的,因为我们在这两种情况下都做了覆盖,而且这两种情况都是相同的,所以看起来这是一个错误...
帖子的旧部分:
请考虑以下代码:
Framework.php
namespace A
{
class Component { ... }
abstract class Decorator {
public abstract function Decorate(\A\Component $component);
}
}
Implementation.php
namespace B
{
class MyComponent extends \A\Component { ... }
}
MyDecorator.php
namespace A
{
class MyDecorator extends Decorator {
public function Decorate(\B\MyComponent $component) { ... }
}
}
以下代码在 MyDecorator.php 告诉
时出错致命错误:MyDecorator :: Decorate()的声明必须与MyDecorator.php中的A \ Decorator :: Decorate()的声明兼容......
但是当我将Framework.php :: Decorator类更改为以下实现时:
abstract class Decorator {
public function Decorate(\A\Component $component) {}
}
问题消失了。
答案 0 :(得分:4)
我不确定(没有测试过它;),但你声明了这个抽象函数:
public abstract function Decorate(\A\Component $component);
所以你应该像这样完全实现。但你这样做了:
public function Decorate(\B\MyComponent $component) { ... }
那不一样。您可以尝试将其更改为\A\Component
吗?
对所有评论:事实是这条PHP“运行”
namespace A
{
class Component { }
abstract class Decorator {
public abstract function Decorate(\A\Component $component);
}
}
namespace B
{
class MyComponent extends \A\Component { }
}
namespace A
{
class MyDecorator extends Decorator {
public function Decorate(\A\Component $component) {}
}
}
这不是:
<?php
namespace A
{
class Component { }
abstract class Decorator {
public abstract function Decorate(\A\Component $component);
}
}
namespace B
{
class MyComponent extends \A\Component { }
}
namespace A
{
class MyDecorator extends Decorator {
public function Decorate(\B\MyComponent $component) {}
}
}
?>
出现此错误:PHP Fatal error: Declaration of A\MyDecorator::Decorate() must be compatible with that of A\Decorator::Decorate() in line 18
现在你可以讨论你应该或不应该如何做的所有内容,但这就是代码的问题。
所以,为了满足自己的好奇心:这也是非法的:
<?php
class Component { }
abstract class Decorator {
public abstract function Decorate(Component $component);
}
class MyComponent extends Component { }
class MyDecorator extends Decorator {
public function Decorate(MyComponent $component) {}
}
?>
这不是名称空间或任何东西。这似乎不合法。
答案 1 :(得分:3)
请参阅http://bugs.php.net/bug.php?id=36601,此问题已被报告为错误但由于懒惰而被拒绝:D
答案 2 :(得分:1)
它与抽象无关。它与类型提示有关。该方法的两个定义不兼容,因为您明确地将参数设置为类型\A\Component
,然后尝试使用\B\Component
重载该方法,因为它会更改方法签名。 Decorate
的任何后续声明必须使用与其父声明相同的类型提示,以使方法签名兼容。
答案 3 :(得分:0)
这可能会帮助某人,并且不迟到。 处理此问题的最佳方法是使用接口。 考虑以下;
<?php
interface Componentor{}
class Component implements Componentor { }
abstract class Decorator {
public abstract function Decorate(Componentor $component);
}
class MyComponent extends Component { }
class MyDecorator extends Decorator {
public function Decorate(Componentor $component) {}
}
?>
用法;
<?php
$c=new Component();
//TODO ....blah blah blah...
$decor=new MyDecorator();
//TODO ....blah blah blah...
$decor->Decorate($c);
?>