我知道多态性规则,我们可以通过像这个代码
这样的参数发送它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()
我怎么知道何时使用或不使用?
答案 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
遵循一个常见的最佳实践:尽可能使用接口而不是具体类,例如在变量声明,参数类型和方法返回类型中。这被认为是最佳做法的原因是:
使用接口进行声明和返回类型会隐藏实现细节,以便将来更容易修改。例如,我们可能会发现代码使用LinkedList
而非ArrayList
更有效。我们现在可以在一个地方轻松地进行此更改,就像实例化列表一样。这种做法对于方法参数类型和方法返回类型尤为关键,因此该类的外部用户不会看到您的类的此实现细节,并且可以自由地更改它而不会影响其代码。
通过使用界面,未来的维护者可能更清楚这个类需要某种List
,但它并不特别需要ArrayList
。如果此类依赖于某些ArrayList
特定属性,即它需要使用ArrayList
方法,那么使用ArrayList<Example> examples = ...
代替List<Example> examples = ...
可能会暗示此代码依赖特定于ArrayList
。
它可以简化测试/模拟以使用更抽象的List
而不是使用具体的类ArrayList
。