谈谈PHP继承的那些事,我的个人见解,php继承那些事见解
网上经常流传出php是语言鄙视链最低端的那个,曾经大学学java,毕设用java,刚出来培训用java的我,在最初工作的2、3年时对php的面向对象也是颇有意见,总觉得【不伦不类】,更别提对js的看法了。但是这些观点都在经历越来越多的项目之后逐渐的淡化,甚至改观。这里面包含着自己对项目、技术有着更多的理解,同时,在这些年里,Web环境、技术也在不停的更新。不过今天不是来聊这些东西的,对于以上的问题,我的观点可以总结为:技术是工具、手段,不合适就升级、换,就这么简单。
话归原题。虽然写php已经是将近8年的功底了,但因为工作关系,经常需要涉及前后端的各种代码,容易精分,也总会记岔。最近发生的一件事情让我觉得,或许写下来能够让自己清醒一点。
在某一年写某个模块时用到了static成员,在实现子类的过程中发现他们也共享着父类这个成员的值,具体来说就是我在某个子类A中改变了那个成员值,在另外一个子类B使用的时候结果意外的得到了A覆盖后的值。当时以为,原来static成员是在从声明的地方开始的整个类别树中共享的。后来一直隐约记得这个结论,在平常的代码里面更谨慎的使用static成员,除非确认写的类是个独立的工具类,不然不轻易使用static。
直到有一天我的老大跟我商量升级我之前写的一个BaseModel,他无意中问我:好像你不喜欢用static成员?我说没有啊,因为考虑到BaseModel会被经常继承成各种Model,如果我在这里用了static的话,将来容易踩坑。他表示不理解,然后过来与我辩论。我很义正言辞的说明了因为static成员会被共享,如果要调用两个不同的子类的时候,那个static成员的变量的值就会像一个全局变量一样不可控。他不同意。于是本着科学的精神,我们写下了一个简短的代码来验证:
class A {
protected static $var1 = null;
public static function test(){
echo get_called_class()。' '.static::$var1.'
';
}
}
class B extends A {
protected static $var1 = 'b';
}
class C extends A {
protected static $var1 = 'c';
}
B::test();
C::test();
很显然,这次是我败了。 我期待的结果是c c,不过其实是b c。 那么这样看起来其实子类的static成员是只在子类这一层共享的。但是我总觉得不对劲,明明在写BaseModel的时候我已经又栽过跟头了,为什么这个验证出来并不支持我那个时候遇到的问题呢?于是我发现我记岔了。年轻多好。后来想起来,原来我这里不用static的原因仅仅是因为设计需要。
我以为我错了。直到前几天又写了几个父子类(不是BaseModel了),大胆的用上了static成员,结果是轰轰烈烈的在自测中又摔了一跤。怎么回事!然后我仔细留意了一下自己这次的用法,将上面的例子改了一下运行:
class A {
protected static $var1 = null;
protected static $var2 = null;
public static function test(){
if(!static::$var2){
static::$var2 = static::$var1;
}
echo get_called_class()。' '.static::$var1.'
';
}
}
class B extends A {
protected static $var1 = 'b';
}
class C extends A {
protected static $var1 = 'c';
}
B::test();
C::test();
结果是
B b
C b
如果说上次的结论是对了,那么这次又怎么解释?这里明明就是表示$var2是A,B,C共享的。$var1和$var2的差别这样看起来仅仅是有声明和没声明的区别。于是我又改成这样:
class A {
protected static $var1 = null;
protected static $var2 = null;
public static function test(){
if(!static::$var2){
static::$var2 = static::$var1;
}
echo get_called_class()。' '.static::$var1.'
';
}
}
class B extends A {
protected static $var1 = 'b';
protected static $var2 = null;
}
class C extends A {
protected static $var1 = 'c';
protected static $var2 = null;
}
B::test();
C::test();
结果是
B b
C c
我当时内心是崩溃的。于是我上了Stack Overflow,发现栽坑的不止我一个。
只有显式的声明出来的static成员才会被视为是只从属于子类的。
只有显式的声明出来的static成员才会被视为是只从属于子类的。
只有显式的声明出来的static成员才会被视为是只从属于子类的。
重要的事情说三遍!不过如果子类很多的话, 动态决定值的成员 每个都这样去声明,就从写代码这件事上失去了用static的意义。一个更好的方法是,把$var2变成一个数组,每个类要用的值放在$var[__CLASS__]里面使用。
不过不管怎么说,如非必要,还是尽量不用static成员继承吧。
还有一个有点类似的“坑”。我们说到private成员的时候,都知道private是指私有的,不会被子类继承。但是有时候写代码的时候会忘记,直到载跟头了才想起来原来是private导致子类找不到该有的成员,或者说是private都在子类声明了,但是因为调用函数时是调用父类函数,结果得到的是父类这个private的值而不是子类的。遇到这种情况不可能又将函数原样的重写在子类里。所以使用private要特别小心。
曾经在使用Rackspace的SDK的时候就看到有些类里面使用了private成员,但是由于他们给出了不必要的打开文件权限,导致代码在我们的服务器上运行不了。那么这个时候本想写个子类覆盖一下这个成员的初始值就好了,结果就因为这是个private成员,而最后需要把所有引用到的地方都拷到自己写的子类里面。为什么我们不直接改SDK,让成员变成protected?因为开发包也许下次就升级了呢?修正之后我们把子类移除就好了。如果修改库代码成了习惯,想升级的时候就没这么欢了。所以说,private成员的使用一定要慎之又慎,如果你也在开发SDK,就更需要考虑使用者是不是需要继承?如果你必须写private,你是不是能够保证代码能够适应各种场景的使用?
除非你有非常充分的理由,static和private都是需要慎重使用的。

aphpdepentioncontiveContainerIsatoolThatManagesClassDeptions,增強codemodocultion,可驗證性和Maintainability.itactsasaceCentralHubForeatingingIndections,因此reducingTightCightTightCoupOulplingIndeSingantInting。

選擇DependencyInjection(DI)用於大型應用,ServiceLocator適合小型項目或原型。 1)DI通過構造函數注入依賴,提高代碼的測試性和模塊化。 2)ServiceLocator通過中心註冊獲取服務,方便但可能導致代碼耦合度增加。

phpapplicationscanbeoptimizedForsPeedAndeffificeby:1)啟用cacheInphp.ini,2)使用preparedStatatementSwithPdoforDatabasequesies,3)3)替換loopswitharray_filtaray_filteraray_maparray_mapfordataprocrocessing,4)conformentnginxasaseproxy,5)

phpemailvalidation invoLvesthreesteps:1)格式化進行regulareXpressecthemailFormat; 2)dnsvalidationtoshethedomainhasavalidmxrecord; 3)

tomakephpapplicationsfaster,關注台詞:1)useopcodeCachingLikeLikeLikeLikeLikePachetoStorePreciledScompiledScriptbyTecode.2)MinimimiedAtabaseSqueriSegrieSqueriSegeriSybysequeryCachingandeffeftExting.3)Leveragephp7 leveragephp7 leveragephp7 leveragephpphp7功能forbettercodeefficy.4)

到ImprovephPapplicationspeed,關注台詞:1)啟用opcodeCachingwithapCutoredUcescriptexecutiontime.2)實現databasequerycachingingusingpdotominiminimizedatabasehits.3)usehttp/2tomultiplexrequlexrequestsandreduceconnection.4 limitesclection.4.4

依赖注入(DI)通过显式传递依赖关系,显著提升了PHP代码的可测试性。1)DI解耦类与具体实现,使测试和维护更灵活。2)三种类型中,构造函数注入明确表达依赖,保持状态一致。3)使用DI容器管理复杂依赖,提升代码质量和开发效率。

DatabasequeryoptimizationinPHPinvolvesseveralstrategiestoenhanceperformance.1)Selectonlynecessarycolumnstoreducedatatransfer.2)Useindexingtospeedupdataretrieval.3)Implementquerycachingtostoreresultsoffrequentqueries.4)Utilizepreparedstatementsforeffi


熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

Video Face Swap
使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

熱工具

WebStorm Mac版
好用的JavaScript開發工具

EditPlus 中文破解版
體積小,語法高亮,不支援程式碼提示功能

SecLists
SecLists是最終安全測試人員的伙伴。它是一個包含各種類型清單的集合,這些清單在安全評估過程中經常使用,而且都在一個地方。 SecLists透過方便地提供安全測試人員可能需要的所有列表,幫助提高安全測試的效率和生產力。清單類型包括使用者名稱、密碼、URL、模糊測試有效載荷、敏感資料模式、Web shell等等。測試人員只需將此儲存庫拉到新的測試機上,他就可以存取所需的每種類型的清單。

SublimeText3 Mac版
神級程式碼編輯軟體(SublimeText3)

Atom編輯器mac版下載
最受歡迎的的開源編輯器