在像Java这样的其他OO语言中,我们可以使用implements
,@override
等关键字/注释覆盖函数。
有没有办法在PHP中这样做?我的意思是,例如:
class myClass {
public static function reImplmentThis() { //this method should be overriden by user
}
}
我希望用户实现自己的myClass::reImplementThis()
方法。
我怎么能用PHP做到这一点?如果有可能,我可以选择它吗?
我的意思是,如果用户没有实现该方法,我可以指定默认方法,还是可以识别该方法未定义(我可以使用method_exists
执行此操作)吗?
<?php
abstract class Test
{
abstract protected function test();
protected function anotherTest() {
}
}
class TestTest extends Test
{
protected function test() {
}
}
$test = new TestTest();
?>
这样,TestTest类必须覆盖函数测试。
这涉及几个OOP科目。
首先,简单地重写父类中声明的方法就像在继承类中重新声明方法一样简单。
E.g:
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中没有多重继承),但可以实现多个接口,并且必须满足每个接口的要求才能使类有效。
就在这里。您可以选择通过扩展类并定义具有与基类中相同名称,函数签名和访问说明符(公共或受保护)的方法来覆盖方法。该方法不应在基类中声明为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获取有关类的更多信息。