Rik*_*aaf 5 java interface mixins
请考虑以下情形:假设您创建了一个接口Foo:
public interface Foo {
public void bar();
}
Run Code Online (Sandbox Code Playgroud)
并且说SomeOldClass某个库中有一个旧类要使用.它已经有了bar()方法,但没有明确实现Foo.
您已为所有实现的类别编写了以下代码Foo:
public <T extends Foo> T callBarOnThird(List<T> fooList){
return fooList.get(2).bar();
}
Run Code Online (Sandbox Code Playgroud)
现在你想让它也适用SomeOldClass.您无权访问此类的源代码,因此无法对其进行修改.
有没有办法声明Foo或类似某种"软"接口,(因为在任何实现所有必需方法的类将被接受作为软接口的隐式实现)?如果没有,您将如何使用尽可能干净的代码解决这个问题?
小智 4
Java 是静态类型和动态绑定的。
动态绑定:这意味着方法签名与其实现之间的链接发生在运行时。例如。
例如
public interface MyInterface {
void doStuff();
}
public class MyFirstImpl implements MyInterface {
@Override
public void doStuff() {
// do some stuff here
}
}
public class MySecondImpl implements MyInterface {
@Override
public void doStuff() {
// do some stuff here
}
}
Run Code Online (Sandbox Code Playgroud)
所以如果你有下一个片段
MyInterface test; // pointing to either MyFirstImpl or MySecondImpl
test.doStuff();
Run Code Online (Sandbox Code Playgroud)
JVM 将在运行时确定doStuff从对象的运行时类型MyFirstImpl或MySecondImpl基于对象的运行时类型调用方法。
静态类型:这意味着 JVM 将在编译时检查是否有方法可以调用,无论实现如何。
例如:
public interface MyInterface {
void doStuff();
}
public class MyFirstImpl implements MyInterface {
// no override here
public void doStuff() {
// do some stuff here
}
}
public class MySecondImpl implements MyInterface {
// no override here
public void doStuff() {
// do some stuff here
}
}
Run Code Online (Sandbox Code Playgroud)
所以如果你有下一个片段
MyInterface test; // pointing to either MyFirstImpl or MySecondImpl
test.doStuff();
Run Code Online (Sandbox Code Playgroud)
编译器会抱怨,因为它无法确保在编译时无论实现如何MyInterface都有一个doStuff方法可以调用(尽管在这种情况下,两个实现都MyInterface定义了一个doStuff方法)。
这可以确保您不会NoSuchMethodException在运行时获得 a ,例如,如果您要通过下一个实现。
public class MySecondImpl implements MyInterface {
// no override here
// no doStuff method
}
Run Code Online (Sandbox Code Playgroud)
这为语言增加了一些类型安全性,但代价是一些刚性(因为您能够比运行时更早地确定问题,因此您的反馈循环更短,代价是所有实现实际上都暴露了方法不能开箱即用)。
你应该如何重构你的代码:
在第三方库上创建一个包装器并从包装器中公开接口。
public interface Foo {
void bar();
}
public class ThirdPartyFooWrapper implements Foo {
private SomeOldClass oldClass;
public ThordPartyFooWrapper (SomeOldClass oldClass){
this.oldClass = oldClass;
}
@Override
public void bar() {
this.oldClass.bar();
}
}
Run Code Online (Sandbox Code Playgroud)
然后,在您的代码中使用ThirdPartyFooWrapper而不是SomeOldClass.
希望这能回答您的问题!
| 归档时间: |
|
| 查看次数: |
91 次 |
| 最近记录: |