java多态

Roh*_*nga 1 java polymorphism

请考虑以下代码:

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();
   }
}
Run Code Online (Sandbox Code Playgroud)

这里我们使用switch case来决定构造什么对象,因此我们构造它并将其分配给b以便使用多态.

多态性给我们带来了什么好处?

现在有一种方法可以避免切换案例.说:有一个从int到String的映射,返回"Derived1"或"Derived2".给定包含类名称的字符串.现在我可以构造一个给定包含类名称的String的对象.就像是:

Base b = construct_obj(str);
Run Code Online (Sandbox Code Playgroud)

库调用construct_obj自动从字节码中找到obj的类,并返回对该对象的引用.然后我可以避免切换案例.通常我会有100个派生类.

Jon*_*eet 5

好吧,你可以创建一个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
            }            
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

请注意,如果您有一个连续的整数范围,则可以使用数组而不是地图.

另一种方法是拥有工厂实例而不是使用构造函数 - 这将是"更安全"(就不延迟错误而言),但可能会显着增加代码.(在C#中使用lambda表达式会很容易; Java 7也可以使它成为一个更好的解决方案.)