magento的rewrite机制和OOP的隐藏特性
2014-01-16 19:50
295 查看
在面向对象编程中,大家都知道类之间有重载(overload)、覆盖(override)、隐藏(hide)三种关系,相信很多人对他们都已经很了解了,所以今天分析的重点也不是这些,而是magento中的rewrite机制,为什么会先提一下oop的三种特性呢,因为我觉得他们和magento的rewrite机制很相似,但相似并非相同,还是先看下代码吧,比较容易理解。
Magento发邮件时,使用的是内置的core/email_template,现在重写这个model的send function,在config.xml添加如下内容:
[php]
view plaincopy
<models>
<core>
<rewrite><email_template>Company_Mymodel_Model_Email_Template</email_template>
</rewrite>
</core>
</models>
然后Company/Mymodel/Model/Email/Template.php添加如下代码:
[php]
view plaincopy
class Company_Mymodel_Model_Email_Templateextends Mage_Core_Model_Email_Template {
public function send($email, $name=null, array $variables = array()) {
//省略,重点不在如何重写send
}
发邮件时可以这么写:
$mailConfirm = Mage::getModel('core/email_template');
$mailConfirm->send(//参数…);
或者
$mailConfirm = Mage::getModel(mymodel /email_template');
$mailConfirm->send(//参数…);
注意调用时的区别(红色字体),一个仍然是调用内置的model,一个是重写的model,你能猜到结果是什么吗?没错,结果永远都是调用Company_Mymodel_Model_Email_Template的send函数。是不是有点像开头提到的隐藏特性,因为给人的感觉就是Company_Mymodel_Model_Email_Template的send吧core的send给隐藏了,我没有说是和覆盖相似,my god,算了还是先贴下三种特性的定义,好好体会下:
/////////////////////////////////////////////////////////////////////////////
重载 是指不同的函数使用相同的函数名,但是函数的参数个数或类型不同。调用的时候根据函数的参数来区别不同的函数。
成员函数被重载的特征
(1)相同的范围(在同一个类中);
(2)函数名字相同;
(3)参数不同;
(4)virtual 关键字可有可无。
覆盖(也叫重写)是指派生类函数覆盖基类函数 是指在派生类中重新对基类中的虚函数(注意是虚函数)重新实现。即函数名和参数都一样,只是函数的实现体不一样。
特征是
(1)不同的范围(分别位于派生类与基类);
(2)函数名字相同;
(3)参数相同;
(4)基类函数必须有virtual 关键字。
“隐藏”是指派生类的函数屏蔽了与其同名的基类函数 是指派生类中的函数把基类中相同名字的函数屏蔽掉了。隐藏与另外两个概念表面上看来很像,很难区分,其实他们的关键区别就是在多态的实现上。什么叫多态?简单地说就是一个接口,多种实现吧。
规则如下
(1)如果派生类的函数与基类的函数同名,但是参数不同。此时,不论有无virtual关键字,基类的函数将被隐藏(注意别与重载混淆)。
(2)如果派生类的函数与基类的函数同名,并且参数也相同,但是基类函数没有virtual 关键字。此时,基类的函数被隐藏(注意别与覆盖混淆)
3种情况怎么执行:1。重载:看参数2。隐藏:用什么就调用什么3。覆盖:调用派生类
///////////////////////////////////////////////////////////////////////////////
因为这里的两个send 名称 参数 返回值都相同,并且基类的send没有virtual限定,所以我说是和隐藏相似。为什么只说相似呢?调用的时候,对于隐藏特性,用什么就调用什么,比如用父类的,就new 父类的对象,用子类,就new子类。但是magento的rewrite 并不是,比如上边写到的两种调用send的方法,一个是getModel的core(即父类),一个是getModel的继承类,按理说应该会调用不同的send,但结果调用的永远都是重写的send。
通过跟踪magento源码发现,在Mage_Core_Model_Config的getGroupedClassName方法中:
$config = $this->_xml->global->{$groupType.'s'}->{$group};
if(isset($config->rewrite->$class)) {
$className= (string)$config->rewrite->$class;
} else {
//。。。。。。
}
在Mage::getModel('core/email_template')的时候,Magento先做了一个判断,因为在前边的config里已经对coremodel email_template进行了rewrite,所以尽管调用的是core的send,执行的仍然是rewrite后的send,假如是隐藏的话,调用core的send,执行的就应该是core的send;所以假如你曾经rewrite过core的email_template,或者是有其他第三方组件rewrite过(当然前提你可能不知道或者忘记了),调试的时候,在core的email_template里改来改去,就是没反应,并且很疑惑,根据oop的隐藏规则,我也是使用Mage::getModel('core/email_template')来调用的,new的core/
email_template,怎么在core/ email_template修改就是没反应呢?因为我之前就碰到过这个问题。殊不知这里根本没有遵循OOP的隐藏原则,因为已经被magento的rewrite机制给改掉了。
Magento发邮件时,使用的是内置的core/email_template,现在重写这个model的send function,在config.xml添加如下内容:
[php]
view plaincopy
<models>
<core>
<rewrite><email_template>Company_Mymodel_Model_Email_Template</email_template>
</rewrite>
</core>
</models>
然后Company/Mymodel/Model/Email/Template.php添加如下代码:
[php]
view plaincopy
class Company_Mymodel_Model_Email_Templateextends Mage_Core_Model_Email_Template {
public function send($email, $name=null, array $variables = array()) {
//省略,重点不在如何重写send
}
发邮件时可以这么写:
$mailConfirm = Mage::getModel('core/email_template');
$mailConfirm->send(//参数…);
或者
$mailConfirm = Mage::getModel(mymodel /email_template');
$mailConfirm->send(//参数…);
注意调用时的区别(红色字体),一个仍然是调用内置的model,一个是重写的model,你能猜到结果是什么吗?没错,结果永远都是调用Company_Mymodel_Model_Email_Template的send函数。是不是有点像开头提到的隐藏特性,因为给人的感觉就是Company_Mymodel_Model_Email_Template的send吧core的send给隐藏了,我没有说是和覆盖相似,my god,算了还是先贴下三种特性的定义,好好体会下:
/////////////////////////////////////////////////////////////////////////////
重载 是指不同的函数使用相同的函数名,但是函数的参数个数或类型不同。调用的时候根据函数的参数来区别不同的函数。
成员函数被重载的特征
(1)相同的范围(在同一个类中);
(2)函数名字相同;
(3)参数不同;
(4)virtual 关键字可有可无。
覆盖(也叫重写)是指派生类函数覆盖基类函数 是指在派生类中重新对基类中的虚函数(注意是虚函数)重新实现。即函数名和参数都一样,只是函数的实现体不一样。
特征是
(1)不同的范围(分别位于派生类与基类);
(2)函数名字相同;
(3)参数相同;
(4)基类函数必须有virtual 关键字。
“隐藏”是指派生类的函数屏蔽了与其同名的基类函数 是指派生类中的函数把基类中相同名字的函数屏蔽掉了。隐藏与另外两个概念表面上看来很像,很难区分,其实他们的关键区别就是在多态的实现上。什么叫多态?简单地说就是一个接口,多种实现吧。
规则如下
(1)如果派生类的函数与基类的函数同名,但是参数不同。此时,不论有无virtual关键字,基类的函数将被隐藏(注意别与重载混淆)。
(2)如果派生类的函数与基类的函数同名,并且参数也相同,但是基类函数没有virtual 关键字。此时,基类的函数被隐藏(注意别与覆盖混淆)
3种情况怎么执行:1。重载:看参数2。隐藏:用什么就调用什么3。覆盖:调用派生类
///////////////////////////////////////////////////////////////////////////////
因为这里的两个send 名称 参数 返回值都相同,并且基类的send没有virtual限定,所以我说是和隐藏相似。为什么只说相似呢?调用的时候,对于隐藏特性,用什么就调用什么,比如用父类的,就new 父类的对象,用子类,就new子类。但是magento的rewrite 并不是,比如上边写到的两种调用send的方法,一个是getModel的core(即父类),一个是getModel的继承类,按理说应该会调用不同的send,但结果调用的永远都是重写的send。
通过跟踪magento源码发现,在Mage_Core_Model_Config的getGroupedClassName方法中:
$config = $this->_xml->global->{$groupType.'s'}->{$group};
if(isset($config->rewrite->$class)) {
$className= (string)$config->rewrite->$class;
} else {
//。。。。。。
}
在Mage::getModel('core/email_template')的时候,Magento先做了一个判断,因为在前边的config里已经对coremodel email_template进行了rewrite,所以尽管调用的是core的send,执行的仍然是rewrite后的send,假如是隐藏的话,调用core的send,执行的就应该是core的send;所以假如你曾经rewrite过core的email_template,或者是有其他第三方组件rewrite过(当然前提你可能不知道或者忘记了),调试的时候,在core的email_template里改来改去,就是没反应,并且很疑惑,根据oop的隐藏规则,我也是使用Mage::getModel('core/email_template')来调用的,new的core/
email_template,怎么在core/ email_template修改就是没反应呢?因为我之前就碰到过这个问题。殊不知这里根本没有遵循OOP的隐藏原则,因为已经被magento的rewrite机制给改掉了。
相关文章推荐
- 警告: 隐式声明与内建函数 ‘printf’ 不兼容 解决方法(转)
- nf_conntrack: table full, dropping packet
- 将Linux下的Android签名对pk8和pem转换为Eclipse下的签名(keystore)
- 用Properties补充hibernate.cfg.xml配置
- vim 编码方式的设置
- CodeSmith 使用教程(16) 使用XMLProperty
- hibernate配置:properties和cfg.xml
- hadoop通信核心:初探RPC
- linux 大量的TIME_WAIT解决办法
- linux学习--fork用法
- Linux系列书籍
- CentOS,重启的常用命令
- shell 返回返回值调用
- 用OpenSceneGraph实现的NeHe OpenGL教程 - 第一课
- Openssl命令的使用
- linux 中 set,env,export,declare显示shell变量的区别
- 让 CentOS 启动时不启动桌面服务
- Linux中keepalive的使用
- linux 环境下c,c++编程(四):GDB调试
- Windows8.1和CentOS6.5双系统安装