1

我对在抽象类中调用通用方法的正确方法有点困惑。使用以下代码:

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 方法时,我get_valid_statuses()使用通常用于静态方法的范围解析运算符调用该方法。我会假设使用以下方法调用该方法:

$valid = Transaction->get_valid_statuses();

但我想这行不通,因为该类从未实际实例化。有人可以提供一些澄清。我无法从 PHP 文档中找到关于抽象类或范围解析运算符的理解。

谢谢!

4

4 回答 4

1

打开错误报告,您将看到严格错误:

非静态方法 Transaction ::get_valid_statuses() 不应静态调用

此错误存在于所有 5.x php 版本中 - 因此出于向后兼容性的原因它确实有效。回到 php4 的黑暗时期,没有办法在类中声明静态方法,所以所有方法都被声明为简单function foo(){ }

您可以在此处了解静态方法。简单来说,调用这个方法之前不需要实例化类(因为abstract关键字不能实例化),而是通过类名和作用域解析操作符来调用。

这也有效,因为在该方法中没有对当前对象 ( $this) 的引用。如果您更改此方法主体以使用 引用其属性/方法之一$this,您将以致命错误结束。

于 2013-09-13T21:11:20.927 回答
0

使用该::运算符(范围解析运算符)并不总是触发 STATIC 方法调用。

在你的情况下,确实如此。您正在使用类名。但是有一些特殊的关键字不会触发静态调用:self, parent, static.

除此之外,还有一个引用当前自己对象的变量:$this.

因此,每当您继承一个带有自己方法的类时,您总是可以像对待当前类一样对待它们,并调用$this->get_valid_statuses(). 这会动态检查当前类中是否存在该函数,或者按降序排列任何父类或父父类,并调用找到的第一个函数。

如果要确保调用父类的函数,请使用parent::get_valid_statuses(). 如果要确保调用 CURRENT 类的方法,请使用self::get_valid_statuses().

在继承类中的静态方法时,static关键字起着重要作用——但由于静态方法通常比帮助你更邪恶,我只想指出手册

继承类的时候怎么办?这取决于。$this作品。它还允许get_valid_statuses()在当前类中覆盖它并扩展它。

parent::get_valid_statuses()Purchase只有当您的类覆盖get_valid_statuses()并想要从父类获取状态时才应该调用它。在这种情况下,您不能调用$this->get_valid_statuses(),因为这将再次调用同一类中的方法,从而导致永无止境的循环。所以parent::$this->是最常用的前缀。

于 2013-09-13T21:25:44.070 回答
0

抽象类不能被实例化,但方法(不是抽象的)可以被称为静态方法。
无论如何,这是非常糟糕的代码风格 - 请考虑不要使用它。

于 2013-09-13T21:02:28.740 回答
0

该方法不是静态的,因此您不应使用静态方法运算符 ( ::)。此外,由于Purchase继承了抽象类,它将自动获取其所有方法,可以使用$this

$valid = $this->get_valid_statuses();
于 2013-09-13T21:03:06.240 回答