#java #oop
#java #ооп
Вопрос:
У меня есть следующие классы: Foo1 расширяет панель, а Foo2 расширяет панель
Я хотел бы передать тип либо Foo1, либо Foo2 в моем методе, чтобы создать либо Foo1, либо Foo2, например:
public Bar createMethod( "either type of Foo1, or Foo2" fooType) {
//returns the foo1 or foo2
}
Есть ли какой-либо подход для достижения этой цели?
Комментарии:
1. Это звучит как проблема XY . Чего вы на самом деле пытаетесь достичь?
Ответ №1:
Вы можете иметь некоторую гибкость, используя дженерики, объявив:
public <T extends Bar> T createMethod(Class<T> foo) {
// do the factoring
retrun (T) foo1 // (or foo2 depending on the foo passed);
}
При этом все следующие присваиваемые значения действительны:
Bar b1 = createMethod(Foo1.class);
Bar b2 = createMethod(Foo2.class);
Foo1 f1 = createMethod(Foo1.class);
Foo2 f2 = createMethod(Foo2.class);
Примечание: во время выполнения вы получите a ClassCastException
, если не вернете ожидаемый тип. Итак, если вы, например, делаете это:
public <T extends Bar> T createMethod(Class<T> foo) {
return (T)new Foo2();
}
и
Foo1 foo1 = createMethod(Foo1.class);
Ответ №2:
Вот код:
public static void main(String args[]){
Bar barB = createMethod(FooB.class);
Bar barA = createMethod(FooA.class);
System.out.println("barB is instance of B " (barB instanceof FooB) );
System.out.println("barA is instance of A " (barA instanceof FooA) );
}
public static Bar createMethod(Class foo) {
if(foo.equals(FooA.class)) {
FooA fooA = new FooA();
return (Bar) fooA;
}
else{
FooB fooB = new FooB();
return (Bar) fooB;
}
}
}
class Bar{}
class FooA extends Bar{}
class FooB extends Bar{}
И ваши FooA и FooB расширяют панель.
Ответ №3:
Java не имеет типов объединения, поэтому подобный тип A | B
в Java невозможен.
В Java 15 были добавлены закрытые типы с помощью JEP 360, поэтому вы можете создать иерархию закрытых типов только с двумя типами, которые нельзя расширить, эффективно имитируя типы объединения для ваших собственных типов.
Передавая экземпляр Class
, вы можете затем использовать отражение для создания экземпляра типа.
public sealed interface FooBar permits Foo, Bar { }
public final class Bar implements FooBar { }
public final class Foo implements FooBar { }
public FooBar createMethod(Class<? extends FooBar> type) {
return type.newInstance();
}
Без закрытых типов вам придется смириться с тем фактом, что сторонние пользователи могут расширять ваши типы, тем самым делая возможными не только два типа в качестве параметров для метода.
Другой возможностью является использование строк и использование Class.forName(String)
для получения типа, связанного с полным классом:
public FooBar createMethod(String type) {
if (type.equals("your.type.Foo") || type.equals("your.type.Bar"))
return Class.forName(type).newInstance();
}
Ответ №4:
Вы можете объявить
public Bar createMethod(Class<? extends Bar> fooType) {
//returns the foo1 or foo2
}
а затем вызвать, как в
Bar bar = createMethod(Foo1.class);