覆盖PHP中的方法? [英] Overriding methods in PHP?

查看:58
本文介绍了覆盖PHP中的方法?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

In other OO languages like Java we can override a function, possible using keywords/annotations like implements, @override etc.

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

Is there a way to do so in PHP? I mean, for example:

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

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

I want user to implement their own myClass::reImplementThis() method.

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

How can I do that in PHP? If it is possible, can I make it optional?

我的意思是,如果用户没有实现该方法,我可以指定一个默认方法还是我可以确定该方法未定义(我可以使用 method_exists 来做到这一点)?

I mean, if the user is not implementing the method, can I specify a default method or can I identify that the method is not defined (can I do this using method_exists)?

推荐答案

这涉及到几个 OOP 主题.

This touches on several OOP subjects.

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

First, simply overriding an method declared in a parent class is as simple as re-declaring the method in an inheriting class.

例如:

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?

如果您想在覆盖方法上重用覆盖方法的逻辑,只需从扩展类调用父方法即可::

If on the overriding method you wan to reuse the logic of the overriden one, it's just a matter of calling the parent's method from the extending class::

class Tommy
{
    public function greet(string $whom)
    {
        // now with more emphasis!!!
        echo parent::greet(strtoupper($whom)) . "!!!!";
    }
}

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

Now Tommy::greet() calls Person::greet(), but modifies the result before returning it.

需要注意的一点是,重写方法必须与被重写方法兼容:方法可见性不能比原始方法限制更多(增加可见性即可),以及的数量和类型required 参数不能与原始声明冲突.

One thing to note is that overriding methods have to be compatible with the overriden one: the method visibility can't be more restrictive than the original one (it's OK to increase visibility), and the number and type of required arguments can't conflict with the original delcaration.

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

This works, because the type of the arguments does not clash with the original, and we have less required arguments than on the parent:

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

但这不是,因为有额外的必需参数.这将导致无法透明地为该类切换原始类,因此会抛出 Warning:

But this doesn't, since there are additional required arguments. This would make impossible to switch the original class for this one transparently, and thus would throw a Warning:


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

此外,您在问题中提到此方法应由用户覆盖".如果您需要客户端类来实际实现该方法,您有两个选择:

Additionally, you mention in your question that "this method should be overriden by the user". If you require client classes to actually implement the method, you have a couple of options:

抽象类和方法

这些方法的实现是空的,并且扩展类必须实现才能有效.在我们将原始类 Person 更改为:

These are methods where the implementation is left empty, and that extending classes have to implement to be valid. In we changed our original class Person to:

abstract class Person {

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

    public abstract function hide();

}

  • 由于该类现在包含一个抽象方法,因此也需要将其声明为抽象类.
  • 现在不能直接实例化Person,只能在其他类中扩展.
  • 现在我们所有现有的 Person 扩展类都会出错,并且尝试执行之前的代码会抛出致命错误.
    • Since now the class contains an abstract method, it needs to be declared as an abstract class as well.
    • Now it is not possible to instantiate Person directly, you can only extend it in other classes.
    • Now all our existing Person extending classes would be wrong, and trying to execute the previous code would throw a fatal error.
    • 现在扩展 Person 的有效类的示例是:

      An example of a valid class extending Person now would be:

      class Archie extends Person {
      
          public function hide() {
              echo "Hides behind a bush";
          }
      }
      

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

      Any class that extends Person must declare a public hide() method.

      接口

      最后,您提到了接口.接口是实现类必须履行的契约.它们声明了一组公共方法没有实现体.

      Finally, you mention interfaces. Interfaces are contracts that implementing classes have to fulfill. They declare a group of public methods without an implementation body.

      例如:

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

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

      Now we could have class that extended Person and implemented 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中没有多重继承),但可以实现多个接口,并且必须满足每个接口的要求类是有效的.

      Importantly, while it's possible to extend only one class (there is no multiple inheritance in PHP), it is possible to implement multiple interfaces, and the requirements for each of those have to be fulfilled for the class to be valid.

      这篇关于覆盖PHP中的方法?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆