2017-01-09 198 views
4

方法我正在尋找一個解決方案,它允許保護繼承的默認方法。最簡單的解決方案可以是 - 從課程等擴展...但在我的情況下,這是不可能的。保護「默認」,從覆蓋

有人建議如何解決這個問題呢?可以有任何解決方法嗎?

大氣壓我有以下的代碼,這需要被重新加工(如果/任何可能的):

public interface MyInterface1 { 
    default boolean isA(Object obj) { 
     return (boolean) obj.equals("A") ? true : false; 
    } 

    default boolean isB(Object obj) { 
     return (boolean) obj.equals("B") ? true : false; 
    } 
} 

public class MyClass extends MyLogic implements MyInterface, MyInterface1 { 
// this class allows to inherit methods from both interfaces, 
// but from my perspective i'd like to use the methods from MyInterface1 as it is, 
// with a 'protection' from inheritance. is that possible? 
} 
+2

1.您是否試圖實現某種多重繼承?它會炸到你的臉上,其餘的Java語言不適合。 2.我不確定它是否會工作,但是您是否嘗試瞭解將默認方法上的「最終」關鍵字時發生的情況? –

+4

不需要所有的冗長,只要說'return obj.equals(「B」);'。 –

+2

這甚至意味着什麼?不管是否有默認實現,接口方法都必須被繼承。 – Brick

回答

5

你似乎想辦法寫你的接口,以便實現類不能提供自己的默認方法的實現。沒有辦法做到這一點,事實上它與一般界面和特定默認成員的目的背道而馳。

的默認方法,關鍵是要提供一種方法方法添加到現有的接口,而無需立即打破他們現有的所有實現。一般來說,這是一個二進制兼容性問題,而不是功能問題。總的來說,沒有什麼特別的理由可以假設默認實現可以提供預期的功能,但是如果沒有它們,甚至不依賴於新方法的舊代碼與添加方法的接口修訂版本不兼容。


我認爲你有一個保理問題。與其試圖強迫類提供特定方法的具體實現 - 甚至不能引用該類的成員,除了可能由其他人定義的成員 - 您應該在自己的類中提供常用方法。畢竟,因爲您希望涉及的所有類都提供相同的實現,所以您實際使用哪個類的實現並不重要。而且,因此在將任何給定的類別標記爲提供公知方法的實現方面沒有特別的用處。

例子:

public class MyImplementation1 { 
    public static boolean isA(Object obj) { 
     return obj.equals("A"); 
    } 

    public static isB(Object obj) { 
     return obj.equals("B"); 
    } 
} 

// Wherever needed, use as MyImplementation1.isA(o), etc. 

你可以做到這一點,即使你希望這些預焙實現在你的界面的其他方法方面工作。在這種情況下,只需向提供對象的固定方法添加一個參數即可。也許這就是你例子中的obj論點應該是這樣的;在這種情況下,這可能是更接近你以後:

public interface MyInterface3 { 
    public String someInterfaceMethod(); 
} 

public class MyImplementation2 { 

    public static boolean isA(MyInterface3 subject) { 
     return subject.someInterfaceMethod().equals("A"); 
    } 

    public static boolean isB(MyInterface3 subject) { 
     return subject.someInterfaceMethod().equals("B"); 
    } 
} 
-1

沒有,這是不可能的,因爲到Java實現了接口(雙關語意)的方式。對於作爲這種情況的原因的詳細信息,請參閱這個問題的答案Why is "final" not allowed in Java 8 interface methods?

但是這裏有一些其他的方式來引導開發未覆蓋默認的方法:

  1. 源代碼註釋

//Do not inherit please

  • Javadoc註釋
  • +0

    你不能避免繼承。你的意思是「不要超越」? –

    +0

    @ MarrieteCowby12請看看這個:http://blog.joda.org/2016/09/private-methods-in-interfaces-in-java-9.html你怎麼看? – Reborn

    +2

    @reborn非常有用的文章,並感謝他們的介紹,但雖然它的確是一個私有方法不能被實現該接口的類重寫,但該類也將無法訪問該方法,因爲它的修飾符是私有的,所以除非你的情況是你不希望實現類使用默認方法的地方,那麼私有修改器將無濟於事。 – SteelToe

    3

    你不能。至少如果你將自己限制在純java編譯器解決方案中。

    而原因是因爲它沒有設計成這樣做:目的是在不破壞實現的情況下向現有接口添加新方法(如java.util.Collection)。這樣一來,我們有sort()stream()forEach()Collection

    如果你允許這樣的事情(禁止實現),那麼這將意味着接口的改變會導致實現的編譯錯誤(因爲它們會覆蓋將被渲染的方法,方法將會被渲染爲final)。那不是目的。

    還有其他一些選項可以做到這一點,取決於你的需要:

    • 抽象類final方法是以前default方法。
    • 測試使用單元測試default行爲。
    • 測試可能的實現並檢查它們是否不覆蓋它。

    最後一種情況大概可以用Reflections很容易做到:你必須列出所有的實現,併爲您有使用Reflections沒有壓倒一切的每個接口的默認方法。

    3

    我想你的意思是你想要寫一個類使用接口的默認方法,但不繼承他們。

    在您的示例代碼中,您試圖通過實現接口來使用默認方法。當你實現一個接口時,通過設計你也可以繼承它的所有方法。這是Liskov替代原則。通過實現接口,您告訴用戶您的類的所有實例都可以替代該接口的實例。但是,如果接口的默認方法沒有被繼承,這不會是真的,所以你會對你的類的用戶撒謊。

    要讓您的類使用接口的默認方法而不繼承它們,請不要實現接口!相反,使用一個幫手類:

    public interface MyInterface1 { 
        default boolean isA(Object obj) { 
         return obj.equals("A"); // or "A".equals(obj) to avoid NullPointerException 
        } 
    
        default boolean isB(Object obj) { 
         return obj.equals("B"); 
        } 
    } 
    
    public class MyClass extends MyLogic implements MyInterface { 
    
        private static class Helper implements MyInterface1 { 
         void doSomeWork() { 
          // do something that calls isA() and isB()... 
         } 
        } 
    
        public void someMethodOfMyClass() { 
         // ... 
         Helper.doSomeWork(); 
         // ... 
        } 
    }