PHP 5.0对象模型深度探索之绑定


Posted in PHP onSeptember 05, 2006

除了限制访问,访问方式也决定哪个方法将被子类调用或哪个属性将被子类访问. 函数调用与函数本身的关联,以及成员访问与变量内存地址间的关系,称为绑定。

在计算机语言中有两种主要的绑定方式—静态绑定和动态绑定。静态绑定发生于数据结构和数据结构间,程序执行之前. 静态绑定发生于编译期, 因此不能利用任何运行期的信息。它针对函数调用与函数的主体,或变量与内存中的区块。因为PHP是一种动态语言,它不使用静态绑定。但是可以模拟静态绑定。

动态绑定则针对运行期产生的访问请求,只用到运行期的可用信息。在面向对象的代码中,动态绑定意味着决定哪个方法被调用或哪个属性被访问,将基于这个类本身而不基于访问范围。

Public和protected成员的动作类似于PHP的前几个版本中函数的动作,使用动态绑定。这意味着如果一个方法访问一个在子类中被覆写的类成员,并是一个子类的实例,子类的成员将被访问(而不是访问父类中的成员)。

看例子6.10. 这段代码输出” Hey! I am Son.” 因为当PHP调用getSalutation, 是一个Son的实例,是将Father中的salutation覆写而来. 如果salutation是public的,PHP将产生相同的结果. 覆写方法的操作很类似。在Son中,对于identify的调用绑定到那个方法。

即使在子类中访问方式被从protected削弱成public, 动态绑定仍然会发生. 按照访问方式使用的原则,增强对于类成员的访问限制是不可能的,所以把访问方式从public改变成protected不可能进行。

Listing 6.10 Dynamic binding 动态绑定

class Father
{
protected $salutation = "Hello there!"; //问候

public function getSalutation()
{
print("$this->salutationn");
$this->identify();
}

protected function identify()
{
print("I am Father.
n");
}
};

class Son extends Father
{
protected $salutation = "Hey!"; //父类中的protected $salutation 被覆写

protected function identify() //父类中的protected identify() 被覆写
{
print("I am Son.
n");
}
};

$obj = new Son();
$obj->getSalutation(); //输出Hey! I am Son.
?>

//注: 在子类中没有覆写getSalutation(),但实际上仍然存在一个getSalutation().这个类中的$salutation和identify()
//与Son子类的实例中的getSalutation()方法动态绑定,所以调用Son的实例的getSalutation()方法,
//将调用Son类中的成员salutation及identify(),而不是父类中的成员salutation及identify().

Private成员只存在于它们所在的类内部. 不像public和protected成员那样,PHP模拟静态绑定. 看例子6.11。它输出”Hello there! I am Father.”,尽管子类覆写了salutation的值,脚本将this->salutation和当前类Father绑定. 类似的原则应用于private方法identify()。

Listing 6.11 Binding and private members

class Father
{
private $salutation = "Hello there!";

public function getSalutation()
{
print("$this->salutationn");
$this->identify();
}

private function identify()
{
print("I am Father.
n");
}
}

class Son extends Father
{
private $salutation = "Hey!";
private function identify()
{
print("I am Son.
n");
}
}

$obj = new Son();
$obj->getSalutation(); //输出Hello there! I am Father.
?>

动态绑定的好处是允许继承类来改变父类的行为,同时可以保持父类的接口和功能,看例子6.12. 由于使用了动态绑定,在deleteUser中被调用的isAuthorized的version 可以由对象的类型来确定。如果是一个普通的user,PHP调用User::isAuthorized会返回FALSE.如果是一个AuthorizedUser的实例,PHP调用AuthorizedUser::isAuthorized,将允许deleteUser顺利执行。

//haohappy注:用一句话说清楚,就是对象类型与方法,属性绑定. 调用一个父类与子类中都存在的方法或访问一个属性时,会先判断实例属于哪种对象类型,再调用相应的类中的方法和属性.

Listing 6.12 动态绑定的好处

class User //用户
{
protected function isAuthorized() //是否是验证用户
{
return(FALSE);
}

public function getName() //获得名字
{
return($this->name);
}

public function deleteUser($username) //删除用户
{
if(!$this->isAuthorized())
{
print("You are not authorized.
n");
return(FALSE);
}

//delete the user
print("User deleted.
n");
}
}

class AuthorizedUser extends User //认证用户
{
protected function isAuthorized() //覆写isAuthorized()
{
return(TRUE);
}
}

$user = new User;
$admin = new AuthorizedUser;

//not authorized
$user->deleteUser("Zeev");

//authorized
$admin->deleteUser("Zeev");
?> 

为什么private的类成员模拟静态绑定? 为了回答这个问题, 你需要回忆一下为什么需要有private成员.什么时候用它们来代替protected成员是有意义的?

private成员只有当你不想让子类继承改变或特殊化父类的行为时才用到,这种情况比你想像的要少, 通常来说,一个好的对象分层结构应当允许绝大多数功能被子类特殊化,改进,或改变—这是面向对象编程的基础之一。一定的情况下需要private方法或变量,例如当你确信你不想允许子类改变父类中的某个特定的部份。

PHP 相关文章推荐
解决phpmyadmin 乱码,支持gb2312和utf-8
Nov 20 PHP
利用static实现表格的颜色隔行显示的代码
Sep 02 PHP
php 什么是PEAR?
Mar 19 PHP
php中判断文件空目录是否有读写权限的函数代码
Aug 07 PHP
PHP移动文件指针ftell()、fseek()、rewind()函数总结
Nov 18 PHP
php表单提交与$_POST实例分析
Jan 26 PHP
thinkphp中字符截取函数msubstr()用法分析
Jan 09 PHP
PHP常用技巧汇总
Mar 04 PHP
php each 返回数组中当前的键值对并将数组指针向前移动一步实例
Nov 22 PHP
用PHP的socket实现客户端到服务端的通信实例详解
Feb 04 PHP
Paypal实现循环扣款(订阅)功能
Mar 23 PHP
PHP实现的随机红包算法示例
Aug 14 PHP
PHP中的串行化变量和序列化对象
Sep 05 #PHP
Windows下的PHP5.0安装配制详解
Sep 05 #PHP
PHP.MVC的模板标签系统(五)
Sep 05 #PHP
PHP.MVC的模板标签系统(四)
Sep 05 #PHP
PHP.MVC的模板标签系统(三)
Sep 05 #PHP
PHP.MVC的模板标签系统(二)
Sep 05 #PHP
PHP.MVC的模板标签系统(一)
Sep 05 #PHP
You might like
PHP中执行MYSQL事务解决数据写入不完整等情况
2014/01/07 PHP
PHP常用编译参数中文说明
2014/09/27 PHP
php视频拍照上传头像功能实现代码分享
2015/10/08 PHP
php常用日期时间函数实例小结
2019/07/04 PHP
Iframe 自动适应页面的高度示例代码
2014/02/26 Javascript
轻松学习jQuery插件EasyUI EasyUI创建树形菜单
2015/11/30 Javascript
BootStrap glyphicons 字体图标实现方法
2016/05/01 Javascript
JS触摸屏网页版仿app弹窗型滚动列表选择器/日期选择器
2016/10/30 Javascript
jQuery实现两列等高并自适应高度
2016/12/22 Javascript
基于vue的下拉刷新指令和滚动刷新指令
2016/12/23 Javascript
解决vue2.x中数据渲染以及vuex缓存的问题
2017/07/13 Javascript
还不懂递归?读完这篇文章保证你会懂
2018/07/29 Javascript
vue component 中引入less文件报错 Module build failed
2019/04/17 Javascript
Node.js实现简单的爬取的示例代码
2019/06/25 Javascript
[06:44]2014DOTA2国际邀请赛-钥匙体育馆开战 开幕式振奋人心
2014/07/19 DOTA
python实现数通设备端口监控示例
2014/04/02 Python
python去掉行尾的换行符方法
2017/01/04 Python
Python正则捕获操作示例
2017/08/19 Python
Centos部署django服务nginx+uwsgi的方法
2019/01/02 Python
pandas DataFrame的修改方法(值、列、索引)
2019/08/02 Python
python元组的概念知识点
2019/11/19 Python
解析python 类方法、对象方法、静态方法
2020/08/15 Python
python简单实现9宫格图片实例
2020/09/03 Python
recorder.js 基于Html5录音功能的实现
2020/05/26 HTML / CSS
韩国爱茉莉太平洋化妆品美国站:Amore Pacific US
2016/10/28 全球购物
Ivory Isle Designs美国/加拿大:婚礼和活动文具公司
2018/08/21 全球购物
外贸主管求职简历的自我评价
2013/10/23 职场文书
吸烟检讨书2000字
2014/02/13 职场文书
2015年实习单位评语
2015/03/25 职场文书
2015年学校后勤工作总结
2015/04/08 职场文书
金榜题名主持词
2015/07/02 职场文书
2016大学军训通讯稿
2015/11/25 职场文书
如何把新闻人物写得立体、鲜活?
2019/08/14 职场文书
Spring Boot两种全局配置和两种注解的操作方法
2021/06/29 Java/Android
关于SpringBoot 使用 Redis 分布式锁解决并发问题
2021/11/17 Redis
微软Win11什么功能最惊艳? Windows11新功能特性汇总
2021/11/21 数码科技