我对多态性感到困惑

时间:2011-02-05 14:37:51

标签: java oop polymorphism

我知道多态性规则,我们可以通过像这个代码

这样的参数发送它
interface Animal {
  void whoAmI();
}

class A implements Animal{

    @Override
    public void whoAmI() {
        // TODO Auto-generated method stub
        System.out.println("A");
    }

}

class B implements Animal{

    @Override
    public void whoAmI() {
        // TODO Auto-generated method stub
        System.out.println("B");
    }

}

class RuntimePolymorphismDemo {

public void WhoRU(List t){
    System.out.println(t.getClass());
}

public static void main(String[] args) {
     A a = new A();
     B b = new B();

     RuntimePolymorphismDemo rp = new RuntimePolymorphismDemo();
     rp.WhoRU(a);
     rp.WhoRU(b);
  }
}

,但

 List<Example> examples = new ArrayList<Example>();

在上面的代码中,我不明白为什么我们必须使用List<Example>

为什么我们不能这样使用?

ArrayList<Example> examples = new ArrayList<Example>();

因为当我们使用List<Example>时,我们无法使用仅存在于ArrayList类中的方法,例如trimToSize()

我怎么知道何时使用或不使用?

4 个答案:

答案 0 :(得分:7)

使用List而不是ArrayList的原因是,当您想要使用List的功能而不关心它的实现时,只需使用基本接口或抽象类就可以提供更大的灵活性。

如果您需要ArrayList的特殊功能,那么您可以指定它,但如果将来您决定将实现更改为ArrayList以外的其他功能,则很难更改(因为您必须在任何地方更改代码)引用它,而不仅仅是底层代码。)

答案 1 :(得分:2)

List是一个界面ArrayList具体类型实施

如果您只需要使用List中的功能,那么您可以将变量声明为List。然后,如果List有用的新实现可用(例如MySuperFastList),您可以在代码中交换它,只需要进行一次更改。

答案 2 :(得分:1)

与扩展您的示例代码相同,我们说:

Animal a=new A();
Animal b=new B();

你可以为一个较少派生的类型分配一个“更多派生类型”而没有任何问题,实际上你可以构造,总是重复你的例子,一个Anymal数组,用一些实例填充它和B istances并在工作中看到多态性通过循环数组并调用每个“Animal”WhoAmI()

答案 3 :(得分:0)

  

这段代码,我不明白为什么我们必须使用List。为什么我们不能这样使用?

ArrayList<Example> examples = new ArrayList<Example>();

首先,请不要觉得你不能这样做 - 这是完全合法的。

由于这是合法的,因此很自然地质疑为什么你经常会看到这样的代码:

List<Example> examples = new ArrayList<Example>();
  

因为当我们使用List时,我们不能使用只在arrayList类中有类似trimToSize()的方法

同样,你对多态性有了很好的把握。这确实是使用List而不是ArrayList的分支。

List<Example> examples = new ArrayList<Example>();

在这里使用接口List而不是具体的类ArrayList遵循一个常见的最佳实践:尽可能使用接口而不是具体类,例如在变量声明,参数类型和方法返回类型中。这被认为是最佳做法的原因是:

  1. 使用接口进行声明和返回类型会隐藏实现细节,以便将来更容易修改。例如,我们可能会发现代码使用LinkedList而非ArrayList更有效。我们现在可以在一个地方轻松地进行此更改,就像实例化列表一样。这种做法对于方法参数类型和方法返回类型尤为关键,因此该类的外部用户不会看到您的类的此实现细节,并且可以自由地更改它而不会影响其代码。

  2. 通过使用界面,未来的维护者可能更清楚这个类需要某种List,但它并不特别需要ArrayList。如果此类依赖于某些ArrayList特定属性,即它需要使用ArrayList方法,那么使用ArrayList<Example> examples = ...代替List<Example> examples = ...可能会暗示此代码依赖特定于ArrayList

  3. 的内容
  4. 它可以简化测试/模拟以使用更抽象的List而不是使用具体的类ArrayList