5

在其他 OO 语言(如 Java)中,我们可以覆盖一个函数,可能使用关键字/注解implements@override

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

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

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

我怎样才能在 PHP 中做到这一点?如果可能,我可以将其设为可选吗?

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

4

3 回答 3

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

    protected function anotherTest() {

    }
}

class TestTest extends Test
{
    protected function test() {

    }
}

$test = new TestTest();
?>

This way the class TestTest must override the function test.

于 2012-12-15T16:04:37.797 回答
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 Tommy
{
    public function greet(string $whom)
    {
        // now with more emphasis!!!
        echo parent::greet(strtoupper($whom)) . "!!!!";
    }
}

现在Tommy::greet()调用Person::greet(),但在返回之前修改结果。

需要注意的一点是,覆盖方法必须与被覆盖的方法兼容:方法可见性不能比原始方法更具限制性(可以增加可见性),并且所需参数的数量和类型不能冲突与原始声明。

这是可行的,因为参数的类型与原始参数没有冲突,而且我们需要的参数比父级要少:

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 中没有多重继承),但可以实现多个接口,并且必须满足每个接口的要求才能使类有效。

于 2019-03-02T11:22:21.757 回答
0

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

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 继承的方法。

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

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

于 2015-12-10T18:31:46.547 回答