加入收藏 | 设为首页 | 会员中心 | 我要投稿 PHP编程网 - 黄冈站长网 (http://www.0713zz.com/)- 数据应用、建站、人体识别、智能机器人、语音技术!
当前位置: 首页 > 站长学院 > PHP教程 > 正文

PHP继承竟然也需要显性基因?

发布时间:2016-10-17 09:26:14 所属栏目:PHP教程 来源:51cto
导读:副标题#e# 网上经常流传出php是语言鄙视链最低端的那个,曾经大学学java,毕设用java,刚出来培训用java的我,在最初工作的2、3年时对php的面向对象也是颇有意见,总觉得【不伦不类】,更别提对js的看法了。但是这些观点都在经历越来越多的项目之后逐渐的淡
副标题[/!--empirenews.page--]

网上经常流传出php是语言鄙视链最低端的那个,曾经大学学java,毕设用java,刚出来培训用java的我,在最初工作的2、3年时对php的面向对象也是颇有意见,总觉得【不伦不类】,更别提对js的看法了。但是这些观点都在经历越来越多的项目之后逐渐的淡化,甚至改观。这里面包含着自己对项目、技术有着更多的理解,同时,在这些年里,Web环境、技术也在不停的更新。不过今天不是来聊这些东西的,对于以上的问题,我的观点可以总结为:技术是工具、手段,不合适就升级、换,就这么简单。

PHP继承竟然也需要显性基因?

话归原题。虽然写php已经是将近8年的功底了,但因为工作关系,经常需要涉及前后端的各种代码,容易精分,也总会记岔。最近发生的一件事情让我觉得,或许写下来能够让自己清醒一点。

在某一年写某个模块时用到了static成员,在实现子类的过程中发现他们也共享着父类这个成员的值,具体来说就是我在某个子类A中改变了那个成员值,在另外一个子类B使用的时候结果意外的得到了A覆盖后的值。当时以为,原来static成员是在从声明的地方开始的整个类别树中共享的。后来一直隐约记得这个结论,在平常的代码里面更谨慎的使用static成员,除非确认写的类是个独立的工具类,不然不轻易使用static。

直到有一天我的老大跟我商量升级我之前写的一个BaseModel,他无意中问我:好像你不喜欢用static成员?我说没有啊,因为考虑到BaseModel会被经常继承成各种Model,如果我在这里用了static的话,将来容易踩坑。他表示不理解,然后过来与我辩论。我很义正言辞的说明了因为static成员会被共享,如果要调用两个不同的子类的时候,那个static成员的变量的值就会像一个全局变量一样不可控。他不同意。于是本着科学的精神,我们写下了一个简短的代码来验证:

  1. class A { 
  2.   protected static $var1 = null; 
  3.   public static function test(){ 
  4.      echo get_called_class().' '.static::$var1.'<br/>'; 
  5.   } 
  6. class B extends A { 
  7.   protected static $var1 = 'b';   
  8. class C extends A { 
  9.   protected static $var1 = 'c';   
  10. B::test(); 
  11. C::test(); 

很显然,这次是我败了。我期待的结果是c c,不过其实是b c。那么这样看起来其实子类的static成员是只在子类这一层共享的。但是我总觉得不对劲,明明在写BaseModel的时候我已经又栽过跟头了,为什么这个验证出来并不支持我那个时候遇到的问题呢?于是我发现我记岔了。年轻多好。后来想起来,原来我这里不用static的原因仅仅是因为设计需要。

我以为我错了。直到前几天又写了几个父子类(不是BaseModel了),大胆的用上了static成员,结果是轰轰烈烈的在自测中又摔了一跤。怎么回事!然后我仔细留意了一下自己这次的用法,将上面的例子改了一下运行:

  1. class A { 
  2.   protected static $var1 = null; 
  3.   protected static $var2 = null; 
  4.   public static function test(){ 
  5.      if(!static::$var2){ 
  6.           static::$var2 = static::$var1; 
  7.      } 
  8.      echo get_called_class().' '.static::$var2.'<br/>'; 
  9.   } 
  10. class B extends A { 
  11.   protected static $var1 = 'b';   
  12. class C extends A { 
  13.   protected static $var1 = 'c';   
  14. B::test(); 
  15. C::test(); 

结果是

  1. B b 
  2. C b 

如果说上次的结论是对了,那么这次又怎么解释?这里明明就是表示$var2是A,B,C共享的。$var1和$var2的差别这样看起来仅仅是有声明和没声明的区别。于是我又改成这样:

  1. class A { 
  2.   protected static $var1 = null; 
  3.   protected static $var2 = null; 
  4.   public static function test(){ 
  5.      if(!static::$var2){ 
  6.           static::$var2 = static::$var1; 
  7.      } 
  8.      echo get_called_class().' '.static::$var2.'<br/>'; 
  9.   } 
  10. class B extends A { 
  11.   protected static $var1 = 'b'; 
  12.   protected static $var2 = null; 
  13. class C extends A { 
  14.   protected static $var1 = 'c'; 
  15.   protected static $var2 = null; 
  16. B::test(); 
  17. C::test(); 

结果是

  1. B b 
  2. C c

我当时内心是崩溃的。于是我上了Stack Overflow,发现栽坑的不止我一个。

只有显式的声明出来的static成员才会被视为是只从属于子类的。

只有显式的声明出来的static成员才会被视为是只从属于子类的。

只有显式的声明出来的static成员才会被视为是只从属于子类的。

(编辑:PHP编程网 - 黄冈站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

热点阅读