重写方法以从派生子类中获取参数


Override method to take argument from a derived subclass

我最终得到了一个解决方案,其中我有两个类层次结构。其中,第一个(迎宾员)层次结构中的类使用第二个(用户)中的类。

这是前任:

class User {}
class Admin extends User {
    function getSecretMessage() {
        return "secret";
    }
}
class Greeter {
    public function hello(User $a) {
        echo "hello!";
    }
}
class AdminGreeter extends Greeter {
    public function hello(Admin $a) {
        parent::hello($a);
        echo "in addition heres a secret of mine: " . $a->getSecretMessage();
    }
}

在这里我有用户和迎宾员的,在 PHP 中我收到错误(严格)

"AdminGreeter::hello 的声明必须与 Greeter::hello 兼容"

我希望AdminGreeter::hello简单地使用来自更专业类(管理员)的数据"扩展"Greeter::hello

我有什么替代方案来构建类似的东西 i PHP ??

我想主要问题是 PHP 不支持"方法重载",因此如果我向AdminGreeter发送一个User实例,它会中断。但是如果我有"方法重载",如果在 User 实例中传递,Greeter::hello将被简单地调用。

这可能是整体糟糕的设计,因为我最终遇到了这个问题,也许有人可以指出我解决这个问题的更好设计。

正如我旁注的,我在开发Objective-C时似乎遇到了同样的问题。

也许您可以考虑将这些"特殊类"使用 Traits 来代替

class User {
    protected $name;
    public function __construct($name) {
        $this->name = $name;
    }
    public function __toString() {
        return $this->name;
    }
}
trait Admin {
    function getSecretMessage() {
        return "secret";
    }
}
class Greeter {
    public function hello(User $a) {
        echo "Hello ", $a, "!", PHP_EOL;
    }
}
class AdminGreeter extends Greeter {
    use Admin;
    public function hello(User $a) {
        parent::hello($a);
        echo "in addition heres a secret of mine: " . $this->getSecretMessage();
    }
}
$x = new User('Natalie');
$y = new AdminGreeter;
$y->hello($x);

为了尽可能保持原始代码:

interface iUser {
    public function getSecretMessage();
}
class Admin implements iUser {
    function getSecretMessage() {
        return 'secrete';
    }
}
class Greeter implements iUser{
    public function hello( iUser $a ) {
        echo 'hello';
    }
    public function getSecretMessage(){}
}
class AdminGreeter extends Greeter {
    public function hello( iUser $a ) {
        parent::hello($a);
        echo ' in addition heres a secrete of mine: ' . $a->getSecretMessage();
    }
}
AdminGreeter::hello( new Admin );

输出hello in addition heres a secrete of mine: secrete