话归原题。虽然写php已经是将近8年的功底了,但由于事情关系,常常须要涉及前后真个各种代码,随意马虎精分,也总会记岔。最近发生的一件事情让我以为,或许写下来能够让自己复苏一点。
在某一年写某个模块时用到了static成员,在实现子类的过程中创造他们也共享着父类这个成员的值,详细来说便是我在某个子类A中改变了那个成员值,在其余一个子类B利用的时候结果意外的得到了A覆盖后的值。当时以为,原来static成员是在从声明的地方开始的全体种别树中共享的。后来一贯隐约记得这个结论,在平常的代码里面更谨慎的利用static成员,除非确认写的类是个独立的工具类,不然不轻易利用static。
直到有一天我的老大跟我商量升级我之前写的一个BaseModel,他无意中问我:彷佛你不喜好用static成员?我说没有啊,由于考虑到BaseModel会被常常继续成各种Model,如果我在这里用了static的话,将来随意马虎踩坑。他表示不理解,然后过来与我辩论。我很义正言辞的解释了由于static成员会被共享,如果要调用两个不同的子类的时候,那个static成员的变量的值就会像一个全局变量一样不可控。他不同意。于是本着科学的精神,我们写下了一个简短的代码来验证:
很显然,这次是我败了。我期待的结果是c c,不过实在是b c。那么这样看起来实在子类的static成员是只在子类这一层共享的。但是我总以为不对劲,明明在写BaseModel的时候我已经又栽过跟头了,为什么这个验证出来并不支持我那个时候碰着的问题呢?于是我创造我记岔了。年轻多好。后来想起来,原来我这里不用static的缘故原由仅仅是由于设计须要。
我以为我错了。直到前几天又写了几个父子类(不是BaseModel了),大胆的用上了static成员,结果是轰轰烈烈的在自测中又摔了一跤。怎么回事!
然后我仔细留神了一下自己这次的用法,将上面的例子改了一下运行:
结果是
如果说上次的结论是对了,那么这次又怎么阐明?这里明明便是表示$var2是A,B,C共享的。$var1和$var2的差别这样看起来仅仅是有声明和没声明的差异。
于是我又改成这样:
结果是
我当时内心是崩溃的。于是我上了Stack Overflow,创造栽坑的不止我一个。
只有显式的声明出来的static成员才会被视为是只从属于子类的。
主要的事情说三遍!
不过如果子类很多的话, 动态决定值的成员 每个都这样去声明,就从写代码这件事上失落去了用static的意义。一个更好的方法是,把$var2变成一个数组,每个类要用的值放在$var[__CLASS__]里面利用。
不过不管怎么说,如非必要,还是只管即便不用static成员继续吧。
还有一个有点类似的“坑”。我们说到private成员的时候,都知道private是指私有的,不会被子类继续。但是有时候写代码的时候会忘却,直到载跟头了才想起来原来是private导致子类找不到该有的成员,或者说是private都在子类声明了,但是由于调用函数时是调用父类函数,结果得到的是父类这个private的值而不是子类的。碰着这种情形不可能又将函数原样的重写在子类里。以是利用private要特殊小心。
曾经在利用Rackspace的SDK的时候就看到有些类里面利用了private成员,但是由于他们给出了不必要的打开文件权限,导致代码在我们的做事器上运行不了。那么这个时候本想写个子类覆盖一下这个成员的初始值就好了,结果就由于这是个private成员,而末了须要把所有引用到的地方都拷到自己写的子类里面。为什么我们不直接改SDK,让成员变成protected?由于开拓包大概下次就升级了呢?改动之后我们把子类移除就好了。如果修正库代码成了习气,想升级的时候就没这么欢了。以是说,private成员的利用一定要慎之又慎,如果你也在开拓SDK,就更须要考虑利用者是不是须要继续?如果你必须写private,你是不是能够担保代码能够适应各种场景的利用?
除非你有非常充分的情由,static和private都是须要慎重利用的。
文章来源:51CTO