PHP中的覆盖方法?

时间:2012-12-15 16:00:52

标签: php oop override implements

在Java等其他OO语言中,我们可以使用implements@override等关键字/注释来覆盖函数。

有没有办法在PHP中这样做?我的意思是,例如:

class myClass {
    public static function reImplmentThis() { //this method should be overriden by user
    }
}

我希望用户实现自己的myClass::reImplementThis()方法。

我怎么能用PHP做到这一点?如果有可能,我可以选择它吗?

我的意思是,如果用户没有实现该方法,我可以指定默认方法,还是可以识别该方法未定义(我可以使用method_exists执行此操作吗?)

3 个答案:

答案 0 :(得分:1)

<?php
abstract class Test
{
    abstract protected function test();

    protected function anotherTest() {

    }
}

class TestTest extends Test
{
    protected function test() {

    }
}

$test = new TestTest();
?>

这样,TestTest类必须覆盖函数测试。

答案 1 :(得分:1)

这涉及几个OOP主题。

首先,简单地覆盖在父类中声明的方法就像在继承类中重新声明该方法一样简单。

例如:

class Person {

    public function greet(string $whom) {
        echo "hello $whom!";
    }

}

class Tommy extends Person {
    public function greet(string $whom = "everyone") {
        echo "Howdy $whom! How are you?";
    }
}

$a = new Tommy();
$a->greet('World');

// outputs:
// Howdy World! How are you?

要注意的一件事是,覆盖方法必须与被覆盖的方法兼容:方法的可见性不能比原始方法严格(可以增加可见性),并且的数量和类型必需的参数不能与原始替代项冲突。

之所以可行,是因为参数的类型与原始参数不冲突,并且我们需要的参数比父参数少

class Leo extends Person {
    public function greet(string $whom = "gorgeous", string $greet = "Whatsup" ) {
        echo "$greet $whom. How are you?";
    }
}

但这不是,因为还有其他必需的参数。这样就不可能透明地切换该类的原始类,从而抛出Warning


class BadBob extends Person {
    public function greet(string $whom, string $greet ) {
        echo "$greet $whom. How are you?";
    }
}

此外,您在问题中提到“该方法应被用户覆盖” 。如果您需要客户端类来实际实现该方法,则有两种选择:

抽象类和方法

这些方法中的实现留为空白,扩展类必须要实现才有效。在此过程中,我们将原来的类Person更改为:

abstract class Person {

    public function greet(string $whom) {
        echo "hello $whom!";
    }

    public abstract function hide();

}
  • 由于该类现在包含一个抽象方法,因此也需要将其声明为一个抽象类。
  • 现在无法直接实例化Person,您只能在其他类中对其进行扩展。
  • 现在我们所有现有的Person扩展类都将是错误的,并且尝试执行先前的代码将引发致命错误。

现在扩展Person的有效类的示例为:

class Archie extends Person {

    public function hide() {
        echo "Hides behind a bush";
    }
}

任何扩展Person的类必须声明一个公共hide()方法。

接口

最后,您提到接口。接口是实现类必须满足的契约。他们声明了一组没有实现主体的公共方法。

例如:


interface Policeman {
    public function arrest(Person $person) : bool;

    public function help($what): bool;
}

现在我们可以拥有扩展Person和实现Policeman的类:

class Jane extends Person implements Policeman {

    public function hide() {
        echo "Jane hides in her patrol-car";
    }

    public function arrest(Person $person): bool{
        // implement arrest method

        return false;
    }

    public function shoot($what): bool {
        // implements shoot() method

        return false;
    }
}

重要的是,虽然仅可以扩展一个类(PHP中没有多重继承),但是可以实现多个接口,并且必须满足每个接口的要求该类有效。

答案 2 :(得分:0)

是的,有。您可以选择通过扩展类并定义具有与基类中相同名称,函数签名和访问说明符(公共或受保护)的方法来覆盖方法。该方法不应在基类中声明为abstract,否则您将需要在派生类中实现它。在你的例子中,它看起来像这样:

class MyClass {
    public static function reImplmentThis() { //this method should be overriden by user
    }
}

class MyDerivedClass extends MyClass {
    public static function reImplmentThis() { //the method you want to call
    }
}

如果用户没有覆盖它,MyDerivedClass仍然会有一个reImplmentThis()方法,一个继承自MyClass的方法。

也就是说,在从派生类调用扩展静态方法时,需要非常小心以避免麻烦。我鼓励您重构代码以扩展实例方法,除非您非常具体地需要扩展静态类。如果您认为没有比扩展静态类更好的方法,请务必理解Late Static Binding

是的,可以检查方法是否已实现,并使用PHP Reflection获取有关课程的更多信息。