Php:覆盖抽象方法出错了

时间:2011-01-16 08:53:16

标签: php

我认为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) {}
    }

问题消失了。

4 个答案:

答案 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);

?>