如何在 C 8 中使用預設介面方法

2021-10-18 16:39:12 字數 3044 閱讀 9112

c# 8 中新增了乙個非常有趣的特性,叫做預設介面方法(又稱虛擬擴充套件方法),這篇文章將會討論 c# 8 中的預設介面方法以及如何使用。

在 c# 8 之前,介面不能包含方法定義,只能在介面中定義方法簽名,還有乙個就是介面的成員預設是public 和 abstract, 在 c# 8 之前,介面不能包含字段,也不能包含private, protected, 或者 internal 的方法成員。如果你在介面中引入了乙個新成員,預設情況下你必須更新實現該介面的所有子類。

在 c# 8 中可以在介面定義方法的預設實現,而且還可以定義介面成員為private,protect,甚至是 static,還有一點挺奇葩的,乙個介面的 protect 成員是不能被實現類所訪問的,相反,它只能在子介面中被訪問,介面的 virtual 成員可以由派生介面 override,但不能被派生類 override,還有一點請注意,介面目前還不能定義例項成員

所謂的預設介面方法指的是介面中定義了乙個預設實現的方法, 如果實現該介面的類沒有實現預設介面方法的話,那麼這個預設介面方法只能從介面上進行訪問,這是乙個很有用的特性,因為它可以幫助開發人員在不破壞現有功能的情況下向介面的未來版本新增新方法。

考慮下面的 ilogger 定義。

public inte***ce ilogger

下面的兩個類擴充套件了ilogger介面並實現了log()方法。

public class filelogger : ilogger

}public class dblogger : ilogger

}

現在假設你想在ilogger介面中新增乙個方法,該方法接受兩個引數:乙個文字乙個日誌級別,下面的**片段展示了日誌級別的列舉類。

public enum loglevel

修改後的 ilogger 介面如下:

public inte***ce ilogger

好了,現在問題來了,因為 ilogger 中新增了乙個 log 方法,你必須要在所有實現該介面的所有子類中實現log(string message, loglevel loglevel)方法,這就很尷尬了,如果不這樣做的話,編譯器肯定是不會放行的,在現實情況下,這個介面實現類可能在多個 dll 中,甚至在多個團隊中,可想而知,這個工作量是非常大並且非常痛苦的。

這就是預設介面方法的應用場景,你可以在介面中定義乙個預設方法是實現,如下**所示:

public inte***ce ilogger

}

這個時候,實現 ilogger 介面的子類可以不實現新的log(string message, loglevel loglevel)方法,因此下面的**也是跑的通的,編譯器不會丟擲任何錯誤。

public class filelogger : ilogger

}public class dblogger : ilogger

}

現在建立乙個filelogger類例項,然後直接呼叫新的帶引數的log()方法,如下**所示:

從上面圖可看出預設介面方法不能被子類繼承,換句話說,子類根本就不知道介面中還有帶引數的log()方法。

現在有乙個非常重要的問題,預設介面方法如何避免菱形問題?換句話說就是 介面的多繼承問題,考慮下面的**清單。

public inte***ce a

public inte***ce b : a

}public inte***ce c : a

}public class myclass : b, c

當編譯上面**時,會丟擲乙個編譯錯誤,說myclass沒有實現a.display()方法,解決這個問題很簡單,在 myclass 中實現一下介面方法就可以了,如下**所示:

public inte***ce a

public inte***ce b : a

}public inte***ce c : a

}public class myclass : b, c

}

接下來就可以生成 myclass 例項了,然後再呼叫display()方法,如下**所示:

static void main(string args)

現在問題來了,到底是哪乙個display()方法被呼叫了呢?為了避免歧義,c# 將會使用最近覆蓋規則,即class.display()方法被最先呼叫。

到這裡,我想你肯定有疑問,抽象類介面是不是很相似了,甚至可以互換了? 雖然抽象類和介面現在看起來在很多方面都很相似,但兩者之間還是有微妙的區別的,具體如下:

預設介面方法允許開發人員利用 trait 程式設計技術,該技術可以讓那些附屬於該方法的不相關型別得以繼續使用,可能你有點懵,我舉個例子:假設你構建好了乙個dll,被很多的開發人員所使用,現在你要發布該 dll 的新版本,比如說往介面中新增了新方法,這個時候你可以定義預設實現,這樣就可以對已使用的開發者進行無感公升級。

在C 8中如何使用預設介面方法詳解

前言 c 8 中新增了乙個非常有趣的特性,叫做 預設介面方法 又稱虛擬擴充套件方法 這篇文章將會討論 c 8 中的預設介面方法以及如何使用。在 c 8 之前,介面不能包含方法定義,只能在介面中定義方python基礎教程法簽名,還有乙個就是介面的成員預設是 public 和 abstract 在 c ...

在C 8中如何使用預設介面方法詳解

c 8 中新增了乙個非常有趣的特性,叫做 預設介面方法 又稱虛擬擴充套件方法 這篇文章將會討論 c 8 中的預設介面方法以及如何使用。在 c 8 之前,介面不能包含方法定義,只能在介面中定義方法簽名,還有乙個就是介面的成員預設是 public 和 abstract 在 c 8 之前,介面不能包含字段...

Java8中使用預設方法實現多重繼承的測試

當乙個類從超類和介面繼承相同的方法時會發生什麼?乙個超類myclass package insping public class myclass 乙個介面myinte ce package insping public inte ce myinte ce 測試類test package inspin...