Подклассы Java от дискретного класса и интерфейса? - PullRequest
0 голосов
/ 28 июня 2018

График ниже описывает иерархию MyClass и MyOtherClass. С помощью Java можно определить переменную, которая может содержать значения либо MyClass, либо MyOtherClass, то есть определение переменной, которая ограничивает значения экземплярами, которые являются подклассами JComponent и реализациями MyInterface, поэтому что функции из JComponent и MyInterface одновременно доступны?

Я понимаю, что нормальный способ сделать это - создать промежуточный абстрактный класс, который расширяет JComponent и реализует MyInterface, поэтому мне интересно, возможно ли такое поведение без этого.

Причина странной иерархии классов заключается в том, что я изначально создал MyAbstractClass для использования в качестве общего визуального типа, а теперь хотел бы добавить к нему некоторые функции, т.е. MyInterface, для использования в других местах. однако мне также понадобится создать несколько новых классов, которые имеют те же дополнительные функции из MyInterface, но не являются экземплярами класса MyAbstract. Было бы неплохо, если бы мне не пришлось создавать дубликат MyAbstractClass, который расширяет какой-то другой промежуточный класс, который расширяет Jcomponent и MyInterface.

o       JComponent
|
|\
| \
|  \
|   o   MyInterface
|   |
|   |\
|   | |
|\  | o MyClass
| | |
| o |   MyAbstractClass
| | |
| | |
| | /
| |/
| |
| o     MyOtherClass

1 Ответ

0 голосов
/ 28 июня 2018

Пока переменная остается того же типа для любого данного экземпляра, вы можете использовать ограниченный сверху тип Generic для переменной и внедрить объект с помощью метода конструктора или мутатора.

Используя вашу иерархию в качестве примера, ниже Foo имеет переменную bar типа T, которая в данном случае должна быть подтипом JComponent и MyInterface. Затем вы можете создать экземпляр Foo, определяющий конкретный тип. На практике вам, вероятно, лучше определить абстрактный подкласс JComponent, который предоставляет методы MyInterface. Таким образом, вы не будете связаны общим типом.

Foo

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

Тот же принцип может быть применен к статическим методам, например ::1010 *

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 { }

MyInterface

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");
    }
}
...