网上经常传言php是处于语言鄙视链顶端的那个。以前大学学java,毕业用java。我只是出来培训和使用java。我也有很多意见,总觉得[不伦不类],更不用说我对js的看法了。然而,这些观点在经历了越来越多的项目后,逐渐淡化甚至改变。这包括我自己对项目和技术的更好理解。同时,这些年Web环境和技术也在不断更新。但今天我不是来谈论这些事情的。对于以上问题,我的观点可以概括为:技术是一种工具,就是说,如果不合适,就升级或者改变,就这么简单。回到原来的话题。虽然写了将近8年的php,但是因为工作关系,经常需要涉及到前后端的各种代码,容易微调,一直背。最近的一件事让我想到,也许把它写下来可以让我清醒。某年写某个模块的时候,用的是静态成员。在实现子类的过程中,我发现它们也共享了父类的这个成员的值。具体的,我在一个子类A中改变了那个成员的值,当使用另一个子类B时,结果不小心得到了A的覆盖值。当时我以为是原来的静态成员在整个类别树中共享开始从声明的地方。后来,我依稀记得这个结论。在普通代码中更谨慎地使用静态成员。除非你确认你写的类是一个独立的工具类,否则不要轻易使用static。直到有一天老板和我商量升级我之前写的一个BaseModel,他无意中问我:你好像不喜欢用静态成员?我说不行,因为考虑到BaseModel经常会被继承成各种Model,如果我这里用static的话,以后很容易踩坑。他说他听不懂,然后过来和我争论。刚才解释了,因为静态成员会被共享,所以如果要调用两个不同的子类,那么那个静态成员的变量的值就会像全局变量一样不可控。他不同意。所以本着科学的精神,我们写了一个简短的代码来验证:}}classBextendsA{protectedstatic$var1='b';}classCextendsA{protectedstatic$var1='c';}B::test();C::test();显然,这次我输了。我期望结果是cc,但实际上是bc。所以看起来子类的静态成员只是在子类级别共享。但是我总觉得哪里不对。很明显,我在写BaseModel的时候又跌跌撞撞了。为什么这个验证不支持我当时遇到的问题呢?于是我意识到我记错了。年轻多好啊。后来想想,原来我这里之所以不用static,只是设计需要而已。我以为我错了。直到前几天,我又写了几个父子类(不是BaseModel),大胆使用静态成员。结果,我又在自测中倒下了。发生了什么!然后我这次仔细注意了自己的用法,把上面的例子改成了运行:$var2=static::$var1;}echoget_called_class().''.static::$var2.'
';}}classBextendsA{protectedstatic$var1='b';}classCextendsA{protectedstatic$var1='c';}B::测试();C::测试();结果是BbCb如果上次的结论是正确的,这次怎么解释呢?这明明就是$var2是A、B、C共享的,$var1和$var2的区别似乎只是声明和未声明的区别。所以我把它改成这样:).''.static::$var2.'
';}}classBextendsA{protectedstatic$var1='b';protectedstatic$var2=null;}classCextendsA{protectedstatic$var1='c';protectedstatic$var2=null;}B::test();C::test();结果是BbCc我当时心都碎了。所以我去了StackOverflow,发现我不是唯一一个被卡住的人。只有显式声明的静态成员才被视为仅子类。只有显式声明的静态成员才被视为仅子类。只有显式声明的静态成员才被视为仅子类。重要的事说三遍!但是,如果子类很多,动态确定值的每个成员都是这样声明的,从写代码这件事上就失去了使用static的意义。更好的方法是将$var2变成一个数组,并使用$var[__CLASS__]中每个类的值。但无论如何,如果不是必须的,尽量不要继承静态成员。还有一个有点类似的“坑”。说到private成员,我们都知道private就是私有的,不会被子类继承。但有时我写代码时,我会忘记它。卡住了才发现,原来是因为private导致子类找不到自己应该有的成员,或者子类中声明了private,但是因为父类函数调用的时候调用了该函数,所以result是父类而不是子类的私有值。在这种情况下,不可能像在子类中那样重写函数。所以使用private要非常小心。在使用RackspaceSDK的时候,看到有些类使用了private成员,但是因为给了不必要的文件打开权限,导致代码无法在我们的服务器上运行。所以这个时候我就想写一个子类来覆盖这个成员的初始值,结果发现因为这是一个私有成员,***需要把所有引用的地方都复制到我写的子类中。为什么我们不直接更改SDK来保护成员?因为下次可能会升级开发包?更正后,我们只是删除子类。如果修改库代码成了习惯,想升级的时候就没那么开心了。因此,私有成员的使用一定要慎重。如果你也在开发SDK,需要考虑用户是否需要继承?如果一定要写private,能不能保证代码可以在各种场景下使用?除非你有很好的理由,否则都需要谨慎使用static和private。
