yii - Yii 行为中的 "Abstract"方法

标签 yii behavior abstract-methods

我一直在开发 Yii 应用程序。我想知道是否可以在模型行为中声明某种“抽象”方法。我知道不可能直接使用以下声明:

abstract class FantasticBehavior extends CActiveRecordBehavior
{
    public abstract function doSomethingFantastic();
}

因为我们需要这个类的一个实例。但我也知道 Yii 充满魔力:)

我只想让所有者类按强制顺序从行为中重新声明方法。当然,除了行为之外我还可以使用界面,但是......

很抱歉,如果我错过了一些要说的事情或者有些事情不清楚。只要提问,我会尽力解释我的意思。

有人知道这件事吗?

提前致谢。

UPD

我确实明白 Yii 只是 PHP。它不扩展 PHP。它是其之上的上层建筑。而且它没有多重继承,因为 PHP 没有。

我确实理解行为方法不能使用抽象关键字声明。这就是为什么我在引号中写了“抽象”一词。但是无所谓。我知道行为是如何运作的。

我的问题是我是否可以以某种方式强制模型(例如 CActiveRecord 的子级)声明某种方法。

例如,出于我的目的,我可以这样做:

class FantasticBehavior extends CActiveRecordBehavior
{
    public function doFantasticThings()
    {
        $this->owner->prepareForFantastic();
        // some code
    }
}

因此,如果我将此行为附加到我的模型并调用方法 doFantasticThings,此方法将尝试从模型(所有者)调用方法prepareForFantastic。如果模型没有声明方法prepareForFantastic,则会抛出新的异常,因为调用了未声明的方法。

看来我自己已经回答了我的问题:)你对此有何看法?

UPD2

是的,我知道如果我们不调用“抽象”方法,我们将不知道它没有被声明。这是可解释语言的“魅力”:)在代码运行之前我们不知道是否有任何错误。不过,如果我们能尽早知道这一点那就太好了。例如,一旦将 FantasticBehavior 类的实例附加到模型,我们就可以抛出 CException 的某些子级以显示必须在模型中声明哪些所需方法。为了实现这一点,我们可以使用如下所列的内容:

class FantasticBehavior extends CActiveRecordBehavior
{

    public function attach($owner)
    {

        if(!/*$owner has declared methods list this->abstractMethods*/)
        {
            throw new CAbstractMethodNotDecalared('....');
        }

        parent::attach($owner);     
    }

    public function abstractMethods()
    {
        return array('prepareForFantastic');
    }

}

我们需要重写类CBehavior中的方法attach并检查是否声明了“抽象”方法。方法abstractMethods用于获取列表“抽象”方法。

我不知道是否存在 attachBehavior 事件。如果是这样,我们可以使用它而不是重写 attach 方法。

使用这个想法基类来实现具有“抽象”方法的行为。

你对此有何看法?

也许将来我会为 Yii 做扩展,变得出名、变得富有? :))

最佳答案

解释起来可能有点困惑......

不,您不能使用 Yii's Behaviors 将抽象方法“附加”到您的 CActiveRecord 模型。所有Behavior所做的都是对__call()__get()__set()的一些巧妙的重写,从而产生了幻觉 多重继承。 (This is a good article about it)。行为不为抽象类和接口(interface)等核心语言功能提供真正的“多重继承”支持。因此,如果您附加该行为并将 doSomethingFantastic() 添加到您的 CActiveRecord 类,您仍然会收到错误。

当然,您可以声明其他行为扩展的抽象行为。因此,如果您创建了另一个扩展了 FantasticBehaviorSuperFantasticBehavior 行为,并在中实现了 doSomethingFantastic(),那么您将美好的。 但它不会强制您在 CActiveRecord 本身中声明 doSomethingFantastic() 方法。

更深入的了解:Yii 的方式 CComponent::_call() override 是结构化的,当您调用一个方法时,它会首先查看是否有任何行为具有该方法,然后在类本身上调用该方法。

行为一开始看起来很酷(混合!),但有时最好记住 PHP 是 single class inheritance language并保持很简单。 ;)

更新:

区别在于,如果在这种情况下可以使用抽象方法,那么当您尝试运行代码(任何代码)时,您会看到“类必须实现方法”错误,并且您的 IDE会突出显示错误。这更多的是一个“编译”时错误(并不是说它确实存在于像 PHP 这样的解释语言中)。

相反,您会在运行时看到“未声明的方法”错误(正如您提到的)。但是,直到实际调用该方法之前您不会看到它,这意味着您不会像抽象定义那样得到很好的早期警告。如果该方法从未被调用,您将不会收到错误,这意味着它并不像抽象 def 那样真正“强制”声明。

抱歉,如果我最初的回答是从太基础的水平开始的,我只是想确保没有误解。这是一个有趣的讨论,让我更多地思考抽象声明的真正作用。谢谢,编码愉快! :)

干杯

关于yii - Yii 行为中的 "Abstract"方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9497763/

相关文章:

php - Yii CDBCommand getText 显示 SQL 中的所有变量

regex - 如何在 yii 中使用正则表达式

xamarin.forms - 找不到 'MaxLength' 的属性、可绑定(bind)属性或事件,或者值和属性之间的类型不匹配

c# - C#中的抽象方法

java - 创建新的抽象方法与接口(interface)方法

php - CDbConnection 无法打开数据库连接 Yii

php - 如何使用 AJAX (jQuery) 下载从 TCPDF (PHP) 生成的 PDF 文件?

css - Sharepoint 2010 + CSS3Pie 无法正常工作,因为关闭行为和指定的 url

cakephp - 树行为 : how to quickly reorder existing data by a certain field?

java - 通过java中的内联创建对象访问私有(private)元素