我对在抽象类中调用常用方法的正确方法感到困惑。使用以下代码:
abstract class Transaction {
abstract public function process();
abstract public function set_status();
protected function get_valid_statuses() {
return array(
'pending',
'approved'
);
}
}
class Purchase extends Transaction {
public function process() {
}
public function set_status( $status ) {
//check against valid statuses
$valid = Transaction::get_valid_statuses();
.......
}
}
显然这段代码远未完成,但应该足以满足这个例子。我想知道为什么会这样,因为我已经测试了它。在我的Purchase类中,当使用set_status方法时,我使用通常用于静态方法的Scope Resolution Operator调用get_valid_statuses()
方法。我会假设使用以下方法调用该方法:
$valid = Transaction->get_valid_statuses();
但我想这不会起作用,因为该类实际上从未实例化过。有人可以提供一些澄清。我无法从关于抽象类或范围解析运算符的PHP文档中找到理解。
谢谢!
答案 0 :(得分:1)
启用错误报告,您会看到严格错误:
非静态方法不应该静态调用Transaction :: get_valid_statuses()
所有5.x php版本中都存在此错误 - 因此它出于向后兼容性原因而起作用。回到php4的黑暗时代,没有办法在类中声明静态方法,因此所有方法都被简单地声明为function foo(){ }
您可以了解静态方法here。简单来说,在调用此方法之前不需要实例化类(并且由于abstract
关键字而无法实例化它),但您可以使用类名和范围解析运算符来调用它。
这也有效,因为此方法中没有对当前对象($this
)的引用。如果您使用$this
更改此方法主体以引用其某个属性/方法,则会以致命错误结束。
答案 1 :(得分:0)
抽象类无法实例化,但方法(非抽象)可以作为静态方法调用 无论如何,这是非常糟糕的代码风格 - 请考虑不使用它。
答案 2 :(得分:0)
该方法不是静态的,因此不应使用静态方法运算符(::
)。另外因为Purchase
继承了抽象类,它会自动获取所有方法,可以使用$this
来使用:
$valid = $this->get_valid_statuses();
答案 3 :(得分:0)
使用::
运算符(作用域解析运算符)并不总是触发STATIC方法调用。
在你的情况下,确实如此。您正在使用类名。但是有些特殊关键字不会触发静态调用:self
,parent
,static
。
除此之外,还有一个变量引用当前的自己的对象:$this
。
因此,无论何时继承一个带有自己方法的类,您都可以像对待当前类一样对待它们,并调用$this->get_valid_statuses()
。这会以降序动态检查当前类或任何父类或父父类中是否存在该函数,并调用找到的第一个函数。
如果您想确保调用父类的功能,请使用parent::get_valid_statuses()
。如果要确保调用CURRENT类的方法,请使用self::get_valid_statuses()
。
static
关键字在继承类中的静态方法时起着重要作用 - 但是因为静态方法通常比帮助你更邪恶,所以我只想指向manual。
继承课时该怎么办?这取决于。 $this
有效。它还允许覆盖当前类中的get_valid_statuses()
并扩展它。
parent::get_valid_statuses()
类覆盖Purchase
并希望从父类获取状态,则应该只调用{p> get_valid_statuses()
。在这种情况下,您无法调用$this->get_valid_statuses()
,因为这将再次调用同一类中的方法,从而导致永无止境的循环。因此,parent::
和$this->
是最常用的前缀。