第九节 绑定 [9]


Posted in PHP onOctober 09, 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 动态绑定
<?php
class Father
{
protected $salutation = "Hello there!"; file://问候

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

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

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

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

$obj = new Son();
$obj->getSalutation(); file://输出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
<?php
class Father
{
private $salutation = "Hello there!";

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

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

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

$obj = new Son();
$obj->getSalutation(); file://输出Hello there! I am Father.
?>动态绑定的好处是允许继承类来改变父类的行为,同时可以保持父类的接口和功能. 看例子6.12. 由于使用了动态绑定,在deleteUser中被调用的isAuthorized的version 可以由对象的类型来确定. 如果是一个普通的user,PHP调用User::isAuthorized会返回FALSE.如果是一个AuthorizedUser的实例,PHP调用AuthorizedUser::isAuthorized,将允许deleteUser顺利执行.

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

Listing 6.12 动态绑定的好处
<?php
class User file://用户
{
protected function isAuthorized() file://是否是验证用户
{
return(FALSE);
}

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

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

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

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

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

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

//authorized
$admin->deleteUser("Zeev");
?> 为什么private的类成员模拟静态绑定? 为了回答这个问题, 你需要回忆一下为什么需要有private成员.什么时候用它们来代替protected成员是有意义的?

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

PHP 相关文章推荐
下载文件的点击数回填
Oct 09 PHP
用PHP实现将GB编码转换为UTF8
Nov 25 PHP
PHP 字符串加密函数(在指定时间内加密还原字符串,超时无法还原)
Apr 28 PHP
php数据库抽象层 PDO
May 07 PHP
ajax完美实现两个网页 分页功能的实例代码
Apr 16 PHP
php使用ob_flush不能每隔一秒输出原理分析
Jun 02 PHP
非集成环境的php运行环境(Apache配置、Mysql)搭建安装图文教程
Apr 12 PHP
PHP微信开发之根据用户回复关键词\位置返回附近信息
Jun 24 PHP
利用laravel搭建一个迷你博客实战教程
Aug 13 PHP
PHP学习笔记之session
May 06 PHP
PHP常见过waf webshell以及最简单的检测方法
May 21 PHP
Laravel框架查询构造器 CURD操作示例
Sep 04 PHP
第十节 抽象方法和抽象类 [10]
Oct 09 #PHP
Extended CHM PHP 语法手册之 DIY
Oct 09 #PHP
使用PHP制作新闻系统的思路
Oct 09 #PHP
一个oracle+PHP的查询的例子
Oct 09 #PHP
为php4加入动态flash文件的生成的支持
Oct 09 #PHP
用PHP编程语言开发动态WAP页面
Oct 09 #PHP
用PHP读注册表
Oct 09 #PHP
You might like
《神奇女侠:血脉》神力女超人大战犯罪公司
2020/04/09 欧美动漫
PHP读写文件的方法(生成HTML)
2006/11/27 PHP
php的日期处理函数及uchome的function_coomon中日期处理函数的研究
2011/01/12 PHP
探讨如何把session存入数据库
2013/06/07 PHP
PHP 5.3和PHP 5.4出现FastCGI Error解决方法
2015/02/12 PHP
Yii2框架引用bootstrap中日期插件yii2-date-picker的方法
2016/01/09 PHP
Laravel框架之解决前端显示图片问题
2019/10/24 PHP
js类中的公有变量和私有变量
2008/07/24 Javascript
用JQuery模仿淘宝的图片放大镜显示效果
2011/09/15 Javascript
JS去除右边逗号的简单方法
2013/07/03 Javascript
html dom节点操作(获取/修改/添加或删除)
2014/01/23 Javascript
动态的绑定事件addEventListener方法的使用
2014/01/24 Javascript
深入理解Javascript里的依赖注入
2014/03/19 Javascript
基于AngularJs + Bootstrap + AngularStrap相结合实现省市区联动代码
2016/05/30 Javascript
js 基础篇必看(点击事件轮播图的简单实现)
2016/08/20 Javascript
如何实现json数据可视化详解
2016/11/24 Javascript
js 获取今天以及过去日期
2017/04/11 Javascript
浅谈在react中如何实现扫码枪输入
2018/07/04 Javascript
[00:57]英雄,你的补给到了!
2020/11/13 DOTA
详解Python实现多进程异步事件驱动引擎
2017/08/25 Python
Python搭建FTP服务器的方法示例
2018/01/19 Python
Python中将变量按行写入txt文本中的方法
2018/04/03 Python
解决pycharm无法识别本地site-packages的问题
2018/10/13 Python
python使用epoll实现服务端的方法
2018/10/16 Python
python实现简单日期工具类
2019/04/24 Python
Python+PyQt5实现美剧爬虫可视工具的方法
2019/04/25 Python
Python如何将模块打包并发布
2020/08/30 Python
物业管理求职自荐信
2013/09/25 职场文书
主题实践活动总结
2014/05/08 职场文书
银行青年文明号事迹材料
2014/05/31 职场文书
爱的奉献演讲稿
2014/09/10 职场文书
国土资源局开展党的群众路线教育实践活动整改措施
2014/09/26 职场文书
关于工作经历的证明书
2014/10/11 职场文书
《鲁班学艺》读后感3篇
2019/11/27 职场文书
vue Element-ui表格实现树形结构表格
2021/06/07 Vue.js
Java 数组的使用
2022/05/11 Java/Android