Java subclass 从离散 class 和接口?

Java subclassing from discrete class and interface?

下图描述了 MyClassMyOtherClass 的层次结构。使用 Java 是否可以定义一个可以保存 MyClassMyOtherClass 值的变量,即将值限制为子 class 的实例的变量定义JComponent 的 ]es 和 MyInterface 的实现,以便 JComponentMyInterface 的功能同时可用?

我意识到这样做的正常方法是创建一个扩展 JComponent 并实现 MyInterface 的中间抽象 class,所以我想知道如果没有这种行为是否可能这样做。

奇怪的 class 层次结构背后的原因是我最初创建 MyAbstractClass 用作通用视觉类型,现在想为其添加一些功能,即 MyInterface,用于其他地方。然而,我还需要制作一些新的 classes,它们具有与 MyInterface 相同的附加功能,但不是 MyAbstract class 的实例。如果我不必创建一个重复的 MyAbstractClass 来扩展一些其他中间 class 扩展 JcomponentMyInterface.

就好了
o       JComponent
|
|\
| \
|  \
|   o   MyInterface
|   |
|   |\
|   | |
|\  | o MyClass
| | |
| o |   MyAbstractClass
| | |
| | |
| | /
| |/
| |
| o     MyOtherClass

只要变量对于任何给定实例保持相同类型,您就可以为变量使用上限通用类型,并通过构造函数或修改器方法注入对象。

以您的层次结构为例,Foo 下方有一个 T 类型的变量 bar,它必然是 JComponent 和 [=22] 的子类型=] 在这种情况下。然后你可以构造一个 Foo 的实例来定义具体类型。实际上,您最好定义一个 JComponent 的抽象子类来提供 MyInterface 方法。这样你就不会被通用类型所束缚。

public class Foo<T extends JComponent & MyInterface> {

    private T bar;

    public Foo(T bar) {
        this.bar = bar;
    }

    public void fooAction() {
        bar.interfaceMethod(); // MyInterface method
        System.out.println(bar.getWidth()); // JComponent method
    }
}

用法

public class Main {

    public static void main(String[] args) {
        Foo<MyClass> a = new Foo<>(new MyClass());
        Foo<MyOtherClass> b = new Foo<>(new MyOtherClass());
        a.fooAction();
        b.fooAction();
    }
}

输出

MyClass
0
MyOtherClass
0

同样的原则也适用于静态方法,例如:

public class Main {

    public static void main(String[] args) {
        staticAction(new MyClass());
        staticAction(new MyOtherClass());
    }

    public static <T extends JComponent & MyInterface> void staticAction(T bar) {
        bar.interfaceMethod();
        System.out.println(bar.getWidth());
    }
}

为了完整起见,本例中使用的类:

MyAbstractClass

public abstract class MyAbstractClass extends JComponent { }

我的界面

public interface MyInterface {

    void interfaceMethod();

}

MyClass

public class MyClass extends JComponent implements MyInterface {

    @Override
    public void interfaceMethod() {
        System.out.println("MyClass");
    }
}

MyOtherClass

public class MyOtherClass extends MyAbstractClass implements MyInterface {

    @Override
    public void interfaceMethod() {
        System.out.println("MyOtherClass");
    }
}