亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

使用抽象類而不是特征的優點是什么?

使用抽象類而不是特征的優點是什么?

翻過高山走不出你 2020-02-03 14:45:15
使用抽象類而不是特征(除了性能)有什么好處?在大多數情況下,抽象類似乎可以用特征代替。
查看完整描述

3 回答

?
眼眸繁星

TA貢獻1873條經驗 獲得超9個贊

我可以想到兩個差異

  1. 抽象類可以具有構造函數參數以及類型參數。特性只能具有類型參數。有人討論過,即使將來特征也可以具有構造函數參數

  2. 抽象類可與Java完全互操作。您可以從Java代碼中調用它們而無需任何包裝。特性只有在不包含任何實現代碼的情況下才可以完全互操作


查看完整回答
反對 回復 2020-02-03
?
阿晨1998

TA貢獻2037條經驗 獲得超6個贊

Scala編程中有一節稱為“是特質還是不特質?”。解決了這個問題。由于第一版可在線獲得,我希望可以在這里引用整個內容。(任何認真的Scala程序員都應該買這本書):

每當實現行為的可重用集合時,您都必須決定要使用特征還是抽象類。沒有嚴格的規則,但是本節包含一些要考慮的準則。

如果該行為不會被重用,則將其設為一個具體的類。畢竟這不是可重用的行為。

如果可以在多個不相關的類中重用它,請使其成為特征。只有特征可以混入類層次結構的不同部分。

如果要在Java代碼中從中繼承,請使用抽象類。由于具有代碼的特征沒有緊密的Java類似物,因此從Java類中的特征繼承往往很尷尬。同時,從Scala類繼承也與從Java類繼承一樣。唯一的例外是,僅具有抽象成員的Scala特性直接轉換為Java接口,因此即使您期望Java代碼從其繼承,您也可以隨意定義這些特性。有關如何一起使用Java和Scala的更多信息,請參見第29章。

如果打算以編譯形式分發它,并且希望外部團體編寫從其繼承的類,則可能傾向于使用抽象類。問題在于,當一個特性獲得或失去一個成員時,任何從其繼承的類都必須重新編譯,即使它們沒有更改。如果外部客戶只會調用行為,而不是繼承行為,那么使用特征就可以了。

如果效率很重要,則傾向于使用課程。大多數Java運行時使對類成員的虛擬方法調用比接口方法調用更快。特性被編譯到接口,因此可能會付出一些性能開銷。但是,僅當您知道所討論的特征構成性能瓶頸并有證據證明使用類實際上可以解決問題時,才應做出此選擇。

如果仍然不知道,請在考慮了上述內容之后,將其作為特征開始。您以后總是可以更改它,通常使用特征可以使更多選項保持打開狀態。

正如@Mushtaq Ahmed提到的,特征不能將任何參數傳遞給類的主構造函數。

另一個區別是治療super

類和特性之間的另一個區別是,在類中,super調用是靜態綁定的,而在特性中,它們是動態綁定的。如果您super.toString在類中編寫代碼,那么您將確切知道將調用哪種方法實現。但是,當您在特征中編寫相同內容時,定義特征時,用于超級調用的方法實現是不確定的。

有關更多詳細信息,請參見第12章的其余部分。

編輯1(2013):

與特質相比,抽象類的行為方式存在細微差異。線性化規則之一是,它保留了類的繼承層次結構,這傾向于將抽象類推到鏈的后面,而特征可以很容易地混合進來。在某些情況下,實際上最好放在類線性化的后一個位置,因此可以使用抽象類。請參閱Scala中的約束類線性化(混合順序)。

編輯2(2018):

從Scala 2.12開始,特征的二進制兼容性行為已更改。在2.12之前,向特性添加或刪除成員都需要重新編譯所有繼承特性的類,即使這些類沒有更改。這是由于在JVM中對特征進行編碼的方式所致。

從Scala 2.12開始,特征可以編譯到Java接口,因此要求有所放松。如果特征執行以下任何一項操作,則其子類仍需要重新編譯:

  • 定義字段(valvar,但是常量可以- final val沒有結果類型)

  • 呼喚 super

  • 主體中的初始化器語句

  • 擴展課程

  • 依靠線性化在正確的特征中找到實現

但是,如果特征不具備,您現在可以在不破壞二進制兼容性的情況下對其進行更新。


查看完整回答
反對 回復 2020-02-03
  • 3 回答
  • 0 關注
  • 752 瀏覽

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號