2014-04-25 57 views
9

我使用看起來沿此線的東西的接口:有沒有辦法將現有的界面變成功能界面?

public interface ObjectListener { 
    public void objectAdded(Object o); 
    public void objectRemoved(Object o); 
} 

目前我使用匿名類來實現該接口,但我不在乎這兩種方法之一。沿此線的東西:

someObject.addListener(new ObjectListener() { 

    @Override 
    public void objectAdded(Object o) { 
     doSomething(o); 
    } 

    @Override 
    public void objectRemoved(Object o) {} 
}); 

現在,我一直在使用新的lambda表達式在Java中8哪裏我能,我想用增加的簡單在這樣的情況。畢竟,我只實現了其中一種方法,但由於接口中有兩種方法,所以我不能在lambda表達式中使用它。

有沒有辦法讓我解決這個限制?

+0

請參閱[此答案](http://stackoverflow.com/questions/21833537/java-8-lambda-expressions-what-about-multiple-methods-in-nested-class/21851111#21851111)... – Holger

+0

+ 1的問題很好。 –

回答

7

爲了在lambda表達式中重用不是函數接口的現有接口,還必須使用新的Java8特性,即默認方法。

在這種情況下,如果您想使用lambda表達式代替匿名類,則必須執行以下操作。

首先,你需要重新定義ObjectListener作爲一個新的接口:

public interface ObjectAddedListener extends ObjectListener { 
    @Override 
    default public void objectRemoved(Object o) {} 
} 

我們只是簡單地添加一個空的默認實現,我們不關心的方法,它離開objectAdded()法作爲界面中唯一的抽象方法。

然後你可以代替任何ObjectListener的使用新的類型,因爲只有一個方法,無需在新接口的實現,你可以在lambda表達式中使用它,就像這樣:

ObjectAddedListener listener = o -> doSomething(o); 
someObject.addListener(listener); 

請注意,如果你想直接在addListener()方法使用這個新類型,你首先需要轉換lambda表達式作爲新定義的類型,像這樣:

someObject.addListener((ObjectAddedListener) o -> doSomething(o)); 
+0

或者,如果您可以編輯'ObjectListener'代碼,您可以簡單地將'{}'作爲'objectRemoved()'的主體來添加,那就是:)不需要繼承和強制轉換。 –

+0

在這種情況下,ObjectListener不是我的代碼,因此需要擴展接口。 – Jazzer

+0

該解決方案僅適用於內部代碼,該代碼永遠不會成爲導出的公共API的一部分,並且會由同一個程序員維護。原因是接口中的默認方法不會導致嘗試實現接口但不實現所有方法的客戶機代碼中的編譯時錯誤。對於客戶端將要訪問的代碼,將方法分離到自己的接口定義中會更好。 – scottb

0

爲重構現有接口的替代方案,是不使用Java 8 lambda表達式的單個抽象方法(SAM)接口是將方法分離爲它們自己的類型。如果接口中的大多數方法都可以用於lambda表達式,這是最合適的。

例如,考慮一個接口,可通過字段名稱對數據模型對象進行編程訪問。接口包含讀取字段,另一個用於突變領域的方法:

interface Accessible { 
    Object acc(String fieldName); 
    void mut(String fieldName, Object val); 
} 

似乎可能,甚至有可能的,這兩種方法可以用lambda表達式更好的表現和簡單使用。爲了實現這一目標,該接口可重構這種方式(就像一個例子,有幾個方法可以做到這一點):

class Accessors { 

    private Accessors() { throw new AssertionError(); } 

    interface Accessor { 
     Object acc(String fieldName); 
    } 

    interface Mutator { 
     void mut(String fieldName, Object val); 
    } 
} 

類,它們提供讀取和寫入訪問數據模型對象現在需要實施Accessors.AccessorAccessors.Mutator。但重要的是,這些接口(現在都是函數接口)可以用作在您的代碼中使用Java 8 lambda表達式的策略。

相關問題