2014-04-25 56 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表达式的策略。

相关问题