[英]Marker interface vs empty abstract class
我在使用標記接口或空抽象類之間做出決定時遇到困難。
我有兩個類BrokerResponse
和Notification
,它們沒有結構相似性。 連接它們的唯一方法是需要訂閱。
void register(Receivable receivable, BrokerObserver observer)
我不喜歡使用Marker Interface
,因為它違反了Interface
的基本定義。 另一方面,使用abstract super
類會讓我感到不舒服,因為這兩個類彼此沒有關系。
在這種情況下,通常更可取的方法是什么?為什么?
我忘了提到, BrokerResponse
本身就是一個抽象類,它有幾個子類來確定各自的類型。
抽象類與標記接口:
標記界面沒有任何問題,並且有一些用例。 選擇這兩者之間,標記界面具有更大的靈活性。
如果您確實要定義類型,請使用接口。
抽象類的目的是提供一個適當的超類,其他類可以從中繼承並共享一個共同的設計 - 您的類沒有共同的設計,也沒有什么可以共享。 此外,如果你將來需要為他們添加一個真正不同的父母,你會把它們都粘在一些有限的設計上並且不會那么靈活。
抽象類的用例列表:
在幾個密切相關的類之間共享代碼。
擴展抽象類的類具有許多常用方法或字段,或者需要除公共之外的訪問修飾符(例如protected和private)。
聲明非靜態或非最終字段,使您能夠定義可以訪問和修改它們所屬對象的狀態的方法。
接口用例:
不相關的類將實現您的接口。
指定特定數據類型的行為,而不考慮誰實現其行為。
多重遺產的優勢。
所有列出的參數都是用於接口的。 由於BrokerResponse
本身就是抽象的並且擁有自己的層次結構,因此這些類沒有共同點的事實更加強大。
作為替代方案,您可以使用標記注釋。 我會考慮堅持這兩種方法中的一種而不是抽象類。
標記界面與標記注釋:
根據Joshua Bloch的' Effective java ':
標記接口與標記注釋相比具有兩個優點。 首先,標記接口定義由標記類的實例實現的類型; 標記注釋沒有。 如果使用標記注釋,則此類型的存在允許您在編譯時捕獲錯誤,直到運行時才能捕獲這些錯誤。 標記接口相對於標記注釋的另一個優點是它們可以更精確地定位。
什么時候應該使用標記注釋?
如果標記適用於除類或接口之外的任何程序元素,則必須使用注釋,因為只能使用類和接口來實現或擴展接口。
什么時候應該使用標記界面?
問問自己這個問題, 我想寫一個或多個只接受具有此標記的對象的方法嗎? 如果是這樣,您應該使用標記接口而不是注釋。 這將使您可以將接口用作相關方法的參數類型,這將帶來編譯時類型檢查的真正好處。
摘要:
如果要定義一個沒有與之關聯的新方法的類型,則可以使用標記接口。
如果要標記類和接口以外的程序元素,以便將來可以向標記添加更多信息,或者將標記放入已經大量使用注釋類型的框架中,那么標記注釋是正確的選擇。
在這種情況下使用空抽象類沒有任何意義,因為Java
沒有多重繼承。 使您的類實現一些標記接口不會改變您的類層次結構,它只是用一些額外的元數據標記您的類。
如果已經標記為Subscribable
類也應該是Writable
。 如果使用空的抽象類,則需要重新設計整個層次結構。 使用標記接口,將Writable
添加到實現列表就很容易了。
注釋它們怎么樣? 你得到的答案是,如果你必須選擇,使用標記界面是這里的方法,但根據你可能需要做的事情使用注釋會更清晰。
事實上,你說你需要讓它們以某種方式“相同”談論一個調用instanceof
並根據它做一些事情。 同樣的事情可以通過isAnnotationPresent
等來實現。
但是,如果你添加一個標記界面,那么如何使它不是一個標記界面 - 只有你需要測試有限數量的類? MyInterface {boolean isSubscribable();}
一些東西MyInterface {boolean isSubscribable();}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.