第九节--绑定


Posted in PHP onNovember 16, 2006

*
+-------------------------------------------------------------------------------+
| = 本文为Haohappy读<<Core PHP Programming>> 
| = 中Classes and Objects一章的笔记 
| = 翻译为主+个人心得 
| = 为避免可能发生的不必要的麻烦请勿转载,谢谢 
| = 欢迎批评指正,希望和所有PHP爱好者共同进步! 
| = PHP5研究中心: http://blog.csdn.net/haohappy2004
+-------------------------------------------------------------------------------+
*/
第九节--绑定
除了限制访问,访问方式也决定哪个方法将被子类调用或哪个属性将被子类访问. 函数调用与函数本身的关联,以及成员访问与变量内存地址间的关系,称为绑定. 
在计算机语言中有两种主要的绑定方式—静态绑定和动态绑定. 静态绑定发生于数据结构和数据结构间,程序执行之前. 静态绑定发生于编译期, 因此不能利用任何运行期的信息. 它针对函数调用与函数的主体,或变量与内存中的区块. 因为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!"; //问候   
       public function getSalutation()   
       {   
           print("$this->salutation\n");   
           $this->identify();   
       }   
       protected function identify()   
       {   
           print("I am Father.<br>\n");   
       }   
   };   
   class Son extends Father   
   {   
       protected $salutation = "Hey!";  //父类中的protected $salutation 被覆写   
       protected function identify()    //父类中的protected identify() 被覆写   
       {   
           print("I am Son.<br>\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
<?php   
   class Father   
   {   
       private $salutation = "Hello there!";   
       public function getSalutation()   
       {   
           print("$this->salutation\n");   
           $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(); //输出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 //用户   
   {   
       protected function isAuthorized()  //是否是验证用户   
       {   
           return(FALSE);   
       }   
       public function getName()  //获得名字   
       {   
           return($this->name);   
       }   
       public function deleteUser($username) //删除用户   
       {   
           if(!$this->isAuthorized())   
           {   
               print("You are not authorized.<br>\n");   
               return(FALSE);   
           }   
           //delete the user   
           print("User deleted.<br>\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 相关文章推荐
利用PHP动态生成VRML网页
Oct 09 PHP
PHP COOKIE设置为浏览器进程
Jun 21 PHP
浅析PHP中的UNICODE 编码与解码
Jun 29 PHP
PHP验证码函数代码(简单实用)
Sep 29 PHP
php查看请求头信息获取远程图片大小的方法分享
Dec 25 PHP
php使用递归函数实现数字累加的方法
Mar 16 PHP
图文介绍PHP添加Redis模块及连接
Jul 28 PHP
CodeIgniter视图使用注意事项
Jan 20 PHP
理清PHP在Linxu下执行时的文件权限方法
Jun 07 PHP
laravel学习笔记之模型事件的几种用法示例
Aug 15 PHP
PHP设计模式之观察者模式定义与用法示例
Aug 04 PHP
php过滤htmlspecialchars() 函数实现把预定义的字符转换为 HTML 实体用法分析
Jun 25 PHP
第八节--访问方式
Nov 16 #PHP
第七节--类的静态成员
Nov 16 #PHP
第六节--访问属性和方法
Nov 16 #PHP
第五节--克隆
Nov 16 #PHP
第四节--构造函数和析构函数
Nov 16 #PHP
第三节--定义一个类
Nov 16 #PHP
第二节--PHP5 的对象模型
Nov 16 #PHP
You might like
PHP简单系统数据添加以及数据删除模块源文件下载
2008/06/07 PHP
PHP 抓取新浪读书频道的小说并生成txt电子书的代码
2009/12/18 PHP
用php来改写404错误页让你的页面更友好
2013/01/24 PHP
PHP会话处理的10个函数
2015/08/11 PHP
php自定义函数实现汉字转换utf8编码的方法
2016/09/29 PHP
CI框架实现优化文件上传及多文件上传的方法
2017/01/04 PHP
设定php简写功能的方法
2019/11/28 PHP
Jquery ThickBox插件使用心得(不建议使用)
2010/09/08 Javascript
基于mootools 1.3框架下的图片滑动效果代码
2011/04/22 Javascript
同一页面多个商品倒计时JS 基于面向对象的javascript
2012/02/16 Javascript
js的[defer]和[async]属性
2014/11/24 Javascript
javascript中的this详解
2014/12/08 Javascript
js实现带圆角的多级下拉菜单效果
2015/08/28 Javascript
JS实现的新浪微博大厅文字内容滚动效果代码
2015/11/05 Javascript
Bootstrap模态框使用详解
2017/02/15 Javascript
angularJs中$http获取后台数据的实例讲解
2018/08/08 Javascript
使用vue-cli3 创建vue项目并配置VS Code 自动代码格式化 vue语法高亮问题
2019/05/14 Javascript
layui--select使用以及下拉框实现键盘选择的例子
2019/09/24 Javascript
Vue 修改网站图标的方法
2020/12/31 Vue.js
[01:13]DOTA2群星解读国服召集令 一起说出回归的理由
2013/07/17 DOTA
Python编程入门之Hello World的三种实现方式
2015/11/13 Python
Python读取一个目录下所有目录和文件的方法
2016/07/15 Python
Python用list或dict字段模式读取文件的方法
2017/01/10 Python
Python实现的微信公众号群发图片与文本消息功能实例详解
2017/06/30 Python
python+selenium实现登录账户后自动点击的示例
2017/12/22 Python
Python实现的txt文件去重功能示例
2018/07/07 Python
python遍历文件夹,指定遍历深度与忽略目录的方法
2018/07/11 Python
在python中利用GDAL对tif文件进行读写的方法
2018/11/29 Python
在Python中使用Neo4j的方法
2019/03/14 Python
搞清楚 Python traceback的具体使用方法
2019/05/13 Python
Python pandas用法最全整理
2019/08/04 Python
100%法国制造的游戏和玩具:Les Jouets Français
2021/03/02 全球购物
法人代表证明书格式
2014/10/01 职场文书
党支部培养考察意见
2015/06/02 职场文书
《艾尔登法环》Boss腐烂树灵很有可能是《黑暗之魂3》的一个废案
2022/04/11 其他游戏
Java对文件的读写操作方法
2022/04/29 Java/Android