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()}