Yii行为中的“抽象”方法

时间:2012-02-29 10:56:28

标签: yii behavior abstract-methods

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

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

因为我们需要这个类的实例。但我也知道Yii是完全神奇的:)

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

很抱歉,如果我遗漏了一些事情,或者有些事情不清楚。请问,我会试着解释一下我的意思。

有人对此有所了解吗?

提前致谢。

UPD

我明白Yii只是PHP。它不会扩展PHP。它是上层建筑。并且它没有多重继承,因为PHP没有。

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

我的问题是,如果我能以某种方式强迫模型(例如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');
    }

}

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

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

使用这个想法基类用于“抽象”方法的行为。

您如何看待这个?

也许将来我会为Yii延伸并成名并富有? :))

1 个答案:

答案 0 :(得分:2)

解释这可能有点令人困惑......

不,您不能使用Yii's Behaviors将抽象方法“附加”到您的CActiveRecord模型。所有行为都是__call()__get()__set()的一些巧妙覆盖,它们赋予多重继承的幻觉。 (This is a good article about it)。行为不提供 true “多重继承”支持核心语言功能,如抽象类和接口。因此,如果您附加该行为并将doSomethingFantastic()添加到CActiveRecord课程,您仍会收到错误。

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

为了更深入的理解:Yii的CComponent::_call()覆盖的方式是结构化的,当你调用一个方法时,它将首先看到是否有任何行为具有该方法,并在类本身上调用该方法。

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

更新:

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

相反,您会在运行时看到“非声明方法”错误(如您所述)。但是在实际调用该方法之前你不会看到它,这意味着你没有像抽象定义那样得到那么好的早期警告。如果那个方法永远不会被调用,那么你就不会得到错误,这意味着它并不像抽象def那样真正“强制”声明。

很抱歉,如果我的初步答案是从一个基本的水平开始,我只是想确定没有误解。这是一个有趣的讨论,让我更多地考虑抽象声明的真正作用。谢谢,快乐的编码! :)

干杯