我一直在开发 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
类,您仍然会收到错误。
当然,您可以声明其他行为扩展的抽象行为。因此,如果您创建了另一个扩展了 FantasticBehavior
的 SuperFantasticBehavior
行为,并在它中实现了 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/