Явский полиморфизм
Рассмотрим следующий код:
public abstract class Base {
public void getAnswer();
}
public class Derived1 extends Base {
public void getAnswer() {
}
}
public class Derived2 extends Base {
public void getAnswer() {
}
}
public class Main {
public final int DERIVED1 = 1;
public final int DERIVED2 = 2;
public Base b;
public static void Main() {
int which_obj = which();
switch (which_obj) {
case DERIVED1: Derived1 derived1 = new Derived1();
// construct object
b = derived1;
break;
case DERIVED2: Derived1 derived1 = new Derived1();
// construct object
b = derived2;
break;
}
b.getAnswer();
}
}
здесь мы используем случай переключения, чтобы решить, какой объект построить, и, соответственно, мы создаем его и присваиваем его b, чтобы использовать полиморфизм.
какое преимущество дает нам полиморфизм?
Теперь есть метод, с помощью которого мы можем избежать случая переключения. скажем: есть преобразование из int в String, которое возвращает "Derived1" или "Derived2". дана строка, содержащая название класса. Теперь я могу создать объект с заданной строкой, содержащей имя класса. что-то вроде:
Base b = construct_obj(str);
библиотечный вызов construct_obj автоматически находит класс obj из байт-кодов и возвращает ссылку на объект. тогда я могу избежать случая переключения. как правило, у меня будет 100 классов производных.
2 ответа
Ну, вы могли бы создать Map<Integer, Class<? extends Base>>
а затем использовать Class.newInstance
создать экземпляр с отражением. Это не будет работать так же хорошо, и есть различные ошибки, которые не будут видны до времени выполнения, но это будет работать.
Вот пример кода.
import java.util.*;
abstract class Base {}
class Derived1 extends Base {}
class Derived2 extends Base {}
public class Test
{
public static void main(String[] args)
{
Map<Integer, Class<? extends Base>> map =
new HashMap<Integer, Class<? extends Base>>();
map.put(1, Derived1.class);
map.put(2, Derived2.class);
int which = 2; // For example
Class<? extends Base> clazz = map.get(which);
if (clazz == null)
{
// Invalid choice. Do whatever.
}
else
{
try
{
Base base = clazz.newInstance();
// Use base
}
catch (InstantiationException e)
{
// Handle exception or whatever
}
catch (IllegalAccessException e)
{
// Handle exception or whatever
}
}
}
}
Обратите внимание, что если у вас есть непрерывный диапазон целых чисел, вы можете использовать массив вместо карты.
Другая альтернатива - иметь фабричные экземпляры, а не использовать конструкторы - это было бы "безопаснее" (с точки зрения отсутствия отложенных ошибок), но, вероятно, значительно больше кода. (В C# было бы легко использовать лямбда-выражения; Java 7 также может сделать это предпочтительным решением.)
Ты можешь позвонить Class.newInstance
Class cl = Class.forName("com.stackru.Derived1");
Base b = cl.newInstance();