靜態方法和實例方法的區別以及如何恰當使用

最近看到同事把一個私有實例方法改成了靜態方法,隱約記得有人曾經跟我說過儘量少用靜態方法,於是就和同事討論了下靜態方法和實例方法有啥區別,到底怎麼用比較合適。

於是在網上搜尋資料,但是很多都是粗略講了下,或者是複製粘貼的。功夫不負苦心人,終於找到一篇文章說了靜態方法和實例方法的文章,並且作者還給出了原文鏈接:ABAP Static vs Instance method – Which to use when? 

下文直接搬運了 孟雨泊 的知乎文章 靜態方法和實例方法的區別以及何時使用

我們都在爭論何時使用靜態方法或實例方法。 在大多數情況下,我們會採用最簡單的方法,但這可能不是正確的方法。 讓我們嘗試探索並確定在確定“靜態”或“實例”時最好的方法是什麼。

在跳入差異和應該使用之前,請先檢查一下靜態方法和實例方法的基礎。

靜態方法

靜態方法是可以與類實例無關地調用的方法。 您只能在Static方法中訪問靜態屬性和靜態事件。

實例方法

實例方法是隻能使用對象引用調用的方法。 實例方法可以訪問實例屬性和實例事件。 

爲什麼不使用靜態方法

從示例代碼中可以看到,創建靜態方法聽起來不錯,而且很有利可圖,因爲在調用方法時不涉及冗長的步驟-聲明引用變量,實例化對象和調用方法。 無需執行這些步驟即可直接調用靜態方法。 但是使用靜態的設計不會像聽起來那樣好。 讓我告訴你爲什麼:

靜態方法無法重新定義

面向對象編程的最重要方面之一是多態性–只要需要,就用更具體的實現替換默認實現。在OO ABAP中,多態性將使用方法重新定義來實現。正如我們在前面的文章“覆蓋靜態方法”中所討論的,我們無法重新定義靜態方法。造成這種情況的主要原因是靜態方法可以獨立運行。使用靜態方法,可以通過顯式指定定義它們的類型來調用它們。這意味着,您可以直接調用實現,而該實現不綁定到實例對象的任何特定實現。

讓我們通過一個簡單的場景來了解這一點–如果您有使用BAPI進行銷售訂單創建的靜態方法。在設計時,此方法僅用於一種業務場景。現在,您想將此用於不同的業務場景。在這種新方案中,您需要在項目上設置一些其他字段,例如“更高級別”項目,確定新項目類別等。您認爲簡單的解決方案是在方法中添加一個代碼塊來執行此邏輯XYZ銷售區域,ZABC訂單類型。您在這裏所做的事情是打開一個框,您將在其中繼續添加越來越多的條件。因此違反了單一責任原則。

如果您具有Instance方法,則可以輕鬆繼承另一個類,重新定義該方法並替換現有的實現。在這個新的實現中,您將設置其他字段並調用Super Method來完成其餘的工作。

單元測試

測試夾具

在ABAP單位中,可以使用稱爲測試夾具的特殊方法設置測試數據。使用此方法後,將在您有權訪問測試數據的地方調用您的測試方法。由於每個ABAP單元測試都應該可以單獨進行操作和測試,因此靜態方法很難進行測試。靜態方法將使用靜態屬性,並且由於它們正在使用靜態屬性,因此您必須在測試夾具方法中始終具有其他邏輯來擺脫它們。

如果您正在使用實例的對象,則可以輕鬆清除它。當實例化一個新對象時,舊對象將被取消引用而無需任何其他邏輯

構造函數

與實例方法的CONSTRUCTOR方法相反,使用靜態方法的設計最終將使用CLASS_CONSTRUCTOR。 如前所述,CLASS_CONSTRUCTOR and CONSTRUCTOR: Who comes before whom?,很難預測何時調用CLASS_CONSTRUCTOR。 首次訪問該類時可以調用CLASS_CONSTRUCTOR,即使已訪問該類以獲得常量值也是如此。 這使其無法操作且無法測試。

在同一會話中重用該實用程序

靜態屬性將綁定到內存,直到會話結束。這意味着,如果僅設置一次值,則在會話結束之前不會清除它們。如果是靜態屬性,則不可能在同一會話中利用相同的邏輯。例如。一個簡單的實用程序類,用於生成應用程序日誌。

舉個例子:

  • 在靜態類的屬性中收集日誌
  • 收集後調用靜態方法以生成應用程序日誌。

該設計似乎完全適合應爲靜態的實用程序類。但這是一個問題,它限制了您在同一會話中再次使用相同的邏輯而不會丟失現有信息。可以說,您正在使用此應用程序日誌收集錯誤。現在,在同一程序中,您將不會生成另一個應用程序日誌來跟蹤執行的活動。由於您已收集了靜態屬性中的所有錯誤,因此除非將其複製到另一個佔位符並調用Utility類以生成跟蹤日誌,否則當您嘗試使用同一Utility類時,您將丟失錯誤日誌數據。

另一方面,您使用實例方法和屬性進行了設計,則可以簡單地創建另一個實例並開始使用它來跟蹤日誌。

總結

因此,基於所有這些事實,我們可以得出以下經驗法則:

  • 如果打算創建靜態方法將使用的任何靜態屬性,請考慮創建實例方法。它將允許您使用多個實例。它還允許您控制何時可以釋放綁定的內存。

  • 如果您認爲將來有機會添加條件邏輯,請使用實例方法。通過利用Redefinition,利用多態來使設計更加靈活

  • 靜態僅應用於對象創建的設計模式,例如Singleton,Factory Method,Abstract Factory,Singleton Factory,以方便對象創建。

  • 靜態應該用於純實用程序類,而不用於助手類。

 

文章看完後,我簡單說下我的理解:

  • 靜態方法之所以不推薦使用是因爲其缺乏擴展性,一旦使用靜態方法,面向對象的繼承多態特性也就不再適用。後續在往靜態方法中添加邏輯就會出現很多 if else,因爲你無法保證不同業務方的要求是一樣的。比較好的做法是創建一個接口或者抽象類,讓不同業務場景自己去實現,這樣即使變化也不會相互影響。

  • 如果一定要使用靜態方法,一定要確保該方法以後不會再出現修改和迭代。靜態方法適用場景:工具方法比如 Math.max(),文件讀寫,單例,工廠模式等;

  • 如果是併發場景,也不推薦使用靜態方法,你無法保證線程安全,有可能存在多個線程同時調用,此時你無法確定得到的結果是否是對的。如果給靜態方法添加鎖就得不償失了,此時,實例方法是一個好的選擇。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章