Java 您能否将对象强制转换到它不支持的接口';不显式实现?
我特别感兴趣的是实现一个应用程序,其中一个(或多个)策略来自第三方库 我有一个第三方库,其类如下:Java 您能否将对象强制转换到它不支持的接口';不显式实现?,java,android,design-patterns,interface,Java,Android,Design Patterns,Interface,我特别感兴趣的是实现一个应用程序,其中一个(或多个)策略来自第三方库 我有一个第三方库,其类如下: public class LibraryClass { public void doSomething() { // ... } } 然后,我用相同的接口创建了自己的类: public class MyClass { public void doSomething() { // ... } } public class Libra
public class LibraryClass {
public void doSomething() {
// ...
}
}
然后,我用相同的接口创建了自己的类:
public class MyClass {
public void doSomething() {
// ...
}
}
public class LibraryClassProxy implements Strategy {
private LibraryClass internal;
public void LibraryClassProxy() {
internal = new LibraryClass();
}
public void doSomething() {
internal.doSomething();
}
}
现在,在我的代码中,我要执行以下操作:
public class MainActivity extends AppCompatActivity {
public interface Strategy {
void doSomething();
}
@Override
protected void onCreate(Bundle savedInstanceState) {
Strategy oneClass = (Strategy)(new MyClass());
Strategy twoClass = (Strategy)(new LibraryClass());
oneClass.doSomething();
twoClass.doSomething();
}
}
在本例中,该方法存在,因此接口在技术上是有效的,但没有显式实现。当我尝试这样做时,它抛出了一个运行时错误:
java.lang.ClassCastException: MyClass cannot be cast to MainActivity$Controls
我知道最坏的情况是,我可以使用一个LibraryClass
来包装实现策略的接口:
public class MyClass {
public void doSomething() {
// ...
}
}
public class LibraryClassProxy implements Strategy {
private LibraryClass internal;
public void LibraryClassProxy() {
internal = new LibraryClass();
}
public void doSomething() {
internal.doSomething();
}
}
但是如果可能的话,我更愿意避免这种情况,特别是因为我正在扩展的类实现了许多其他接口,而且我不必代理每一个公共方法。来自:
定义新接口时,就是在定义新的引用数据
类型。可以在任何可以使用任何其他数据的地方使用接口名称
键入名称。如果定义类型为的引用变量
接口,指定给它的任何对象都必须是类的实例
它实现了接口
因此,您不能将对象强制转换为未显式实现的接口您想要实现的基本形式是:您有一个带有
doSomething
方法的接口,并且您希望能够将该方法的任何内容作为该接口的实现,即使它没有明确指定它实现接口
你不能用Java做那种duck类型;所有类型关系都必须是显式的。但是使用lambdas和SAM转换,您可以做一些非常接近的事情
public class MainActivity extends AppCompatActivity {
public interface Strategy {
void doSomething();
}
@Override
protected void onCreate(Bundle savedInstanceState) {
Strategy oneClass = new MyClass()::doSomething;
Strategy twoClass = new LibraryClass()::doSomething;
oneClass.doSomething();
twoClass.doSomething();
}
}
使用所需对象的
doSomething
方法创建新的Strategy
对象,而不是尝试强制转换(您不能这样做)。就个人而言,这感觉像是一个肮脏的黑客,但嘿,这正是你想要的。正如其他人所指出的,在Java中,接口定义是基于显式声明的。我相信您描述的情况包含在设计模式中,而不是代理中:
Intent:将一个类的接口转换为客户端期望的另一个接口。适配器允许由于接口不兼容而无法正常工作的类协同工作---共和党。139
您指出的“代理”解决方案对应于适配器模式的对象。如果<代码> LibraryClass < /代码>不是最终的,则要考虑的一个选项是使用模式的<强>类< /强>变体:
class MyLibraryClass extends LibraryClass implements Strategy {
/* ... */
}
方法定义是不相关的。一个对象必须实现要转换到它的类/接口。给出这个公认的答案是因为有一个非常优雅的解决方案(扩展
LibraryClass
,所以我不必重新实现任何方法)。当我测试它时,有一个小小的警告:Java抱怨LibraryClass
没有默认构造函数(老实说:我不知道如何指定“默认”构造函数),所以我必须为MyLibraryClass
实现一个构造函数,比如:publicMyLibraryClass(){super()}