簡體   English   中英

多變量方法的實例方法與靜態方法

[英]Instance vs Static methods for multiple variable methods

如果您擁有Point3類並具有名為Distance的方法,則應將其靜態化,如下所示:

Point3.Distance ( p1, p2 );

或類似的實例方法:

this.Distance ( p );

我意識到使用靜態方法會阻礙繼承和覆蓋,對嗎?

哪一個更好,為什么?

我更喜歡靜態版本。 (這是我們在SlimDX中全面完成的工作,除了一些“特殊”操作。)原因是Distance從概念上講是一個處理兩個點並產生結果的函數。 您沒有在p1上運行“ Distance”操作,而將p2作為值。

簡而言之,我更喜歡實例方法在概念上是綁定到特定實例的操作。 對於某些人來說,這兩種方式都可以。 例如,SlimDX同時包含Vector3 Normalize函數的靜態版本和非靜態版本,因為這兩種構造都非常方便。 實例一個修改其對象,而靜態一個返回一個新對象。

[編輯]另一個答案提到“ DistanceTo”函數,該函數將是一個實例函數。 盡管這不一定合理,但這是一個設計方向,使我感到不安。 問題是正交性。 一旦添加了更多此類重載(一些靜態實例,某些實例,也許是MathHelper類中的某些實例,誰知道),您就會獲得越來越多的方法來執行相同的操作。 對於庫的復雜性,測試復雜性,錯誤表面積等而言,這是個壞消息。我們選擇在SlimDX中的某些地方進行此操作,但這只是很多類中的少數幾個選擇(並且每個人都被團隊審查過) )。 它可以在一定程度上幫助庫的可用性,但是很容易陷入錯誤的一面。

我更喜歡靜態版本,但是根據您使用它的方式或期望使用它的方式,我會考慮包括一個調用靜態方法的實例方法DistanceTo 有時,這樣的實例方法可以使代碼更簡明易懂。

此類靜態方法的一大賣點是,即使它們的一個或兩個操作數為null ,它們也可以返回結果。 如果只有實例方法,則需要在調用該方法之前對其進行測試以檢查是否為null Object.Equals / ReferenceEquals是一個典型的例子。

“哪一個更好?” 這個問題在很大程度上取決於具體情況。 在某些情況下,您可能需要靜態方法,而在其他情況下,則可能需要實例方法。 我不是在試圖提供一個絕對的命令,而是關於如何做出此決定的一些想法。

清晰度注意事項

當使用對象的實例很尷尬時,可以使用靜態方法。 例如,.NET字符串類具有String.Concat(),其可以連接多個字符串。

顯然有: String.Concat( "A", "B" ); 有: "A".Concat( "B" );

有時,為操作提供名稱而不是將其編碼為構造函數重載是很清楚的。 Int.Parse()是一個很好的例子。 Int可能有一個采用字符串的構造函數,但尚不清楚其意圖是什么。 靜態Parse()方法增加了清晰度。

可維護性注意事項

有時您別無選擇,只能將函數實現為靜態實用程序方法。 可能無法在類中添加新方法-您可能沒有源代碼,可能希望避免測試影響等。

即使可以添加實例方法,通過在實用工具類中實現不常見或專用的方法來整理類也可能很有用。 但是,只有在可以使用要擴展類型的公共接口實現實用程序類時,才應該這樣做。 在C#3.5中,您可以使用擴展方法來創建一種幻覺,即實用程序方法是該類的實例方法。

多態性注意事項

如果某個函數很可能被派生類型覆蓋,則應使其成為實例成員,並使用virtual關鍵字對其進行標記。 沒有標記為虛擬的實例方法沒有比靜態方法可擴展的。

最佳做法注意事項

靜態函數(通常)應該沒有副作用。 換句話說,它們不應修改其任何一個參數的狀態。 具有副作用的函數最好作為對象的實例方法來實現。

在OOP中,有一個單一責任原則 (SRP),該原則基本上指出“每個階層都只有一個改變的理由”。 如果將實例方法添加到特定類將違反SRP,請考慮將該邏輯從類中分解出來。

可用性注意事項

有時,代碼(尤其是框架級代碼)的設計目標是可用性。 在這種情況下,可能同時提供的實例與功能的靜態版本是有用的。 但是,在這種情況下,強烈建議將實例版本實現為對靜態版本的調用。 這種方法允許該類的消費者決定哪個才有意義。 此方法的一個示例是string.Compare()string.CompareTo()方法-前者是靜態的,而后者是實例方法。 這允許字符串類符合特定的接口(IComparable),同時還提供了一種不錯的語法: string.Compare( "A", "a" )

我更喜歡實例方法。 我想說

myPoint.distanceTo(another);

這聽起來可能很愚蠢,但事實是我為另一個元素“ that”准備了一個簡潔易記的名稱,這是使我傾向於此偏好的一部分:

double distanceTo(Point that) {
    double dx = this.x - that.x;
    double dy = this.y - that.y;
    return Math.sqrt(dx^2 + dy^2);
}

(對不起,我的Java;我確定C#並沒有太大不同)。 “ this”和“ that”可以很好地協同工作,我認為使代碼比“ a”和“ b”更易於理解。 另外,如果它是一個實例方法,那么從我的其他實例方法中,我可以使用distanceTo()而不顯式傳遞this

我一直認為static是邪惡的地方,只有在確切知道何時以及為什么需要在類級別進行訪問時,才使用它們。

您可能還會發現其他一些有用的答案。

馬克在“ 何時在C#中使用靜態類 ”的答案

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM