我一直在开发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延伸并成名并富有? :))
答案 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那样真正“强制”声明。
很抱歉,如果我的初步答案是从一个基本的水平开始,我只是想确定没有误解。这是一个有趣的讨论,让我更多地考虑抽象声明的真正作用。谢谢,快乐的编码! :)
干杯