Пока переменная остается того же типа для любого данного экземпляра, вы можете использовать ограниченный сверху тип 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");
}
}