作为一项规则,在大型项目的环境中,将现有的,无处不在的使用界面纳入功能界面是否安全?
,例如,给定现有的界面和类:
public interface Interface {
public double calculateSomething(double x);
public void doSomething();
}
由
实现class InterfaceImplementer implements Interface {
public double calculateSomething(double x) {
return 2 * x;
}
public void doSomething() {
// insert specific behavior here
}
}
我可以通过定义除一个方法之外的所有方法来安全地更改界面:
public interface Interface {
public double calculateSomething(double x);
default void doSomething() {
// insert some default behavior here
}
}
这样我就可以将对象定义为
Interface object = new InterfaceImplementer() {
@Override
public double calculateSomething(double x) {
return 2 * x;
}
};
到
Interface object = (x) -> 2 * x;
虽然仍然能够以旧的,乏味的方式定义对象。
据我所知,这不会冒任何现有代码的风险,而且我已经对大型项目进行了这样的更改,并且没有运行时或编译错误。但我想要确认这是否符合常识和最佳实践。
答案 0 :(得分:8)
任何只有一个非默认方法的接口(只需要在一个类中实现一个方法)根据定义是一个功能接口。这是一个很好的规则!
但是,@FunctionalInterface
注释的优点是强制执行接口中只有一种方法用于功能接口" -rule。因此,如果将其添加到原始的双方法接口,则会出现编译器错误。因此,通过明确添加@FunctionalInterface
,您可以声明自己的意图,并使未来的维护者更清楚地了解您的代码。
答案 1 :(得分:3)
在java代码级别上,我可以想到一个问题:由于此接口在过去的某个时刻已经包含了2个方法,您可能希望稍后再添加另一个方法。您无法将另一种方法添加到功能界面,因为它必须保持功能界面,因此您可以将其用作功能界面。您必须创建一个继承自此接口的接口。这引出了我的主要观点。
以前在一个界面中使用这两种方法可能是合乎逻辑的,但现在它是否合乎逻辑? 重构代码,分离接口;要么将一个扩展为另一个,要么使用继承自两者的接口。如果要将接口用作功能接口,请使其正常工作。它会很干净。这是可以理解的。您将来可以在不进行进一步重构的情况下向其中一个接口添加方法。
答案 2 :(得分:1)
答案 3 :(得分:1)
嗯,不是@Functional
可能会破坏任何东西,但添加默认实现可能会导致实现的抽象类或扩展多个接口的接口的编译错误,声明具有覆盖等效签名的方法:
以下编译正常:
interface I {
void a();
}
interface J {
void a();
}
interface K extends I, J {}
虽然没有:
interface I {
default void a() {}
}
interface J {
void a();
}
interface K extends I, J {}
从I继承的默认方法a()与从J
继承的另一个方法冲突
因此,如果您在库中执行此操作,则使用此代码的代码可能无法在更改后进行编译。