在Java多态中,所有实现接口的类都可以创建为该类型的接口吗?

In Java polymorphism, can all the classes that implements an interface be created as that type interface?

在继续我的在线教程时,我遇到了这节课。我有一个接口和两个实现该接口的 classes。

public interface Payable {
double getPaymentAmount();
}

现在在测试class中,当创建对象数组时,对象的类型被称为Payable[]而不是SalariedEmployee[]Invoice[],比如

    public static void main(String[] args) {
    Payable[] payableObjects = new Payable[4];
    payableObjects[0] = new Invoice("0000", "abc", 1,2);
    payableObjects[1] = new SalariedEmployee("test", "user", "000-000", 35);

你的问题标题不符合语法,但选词表明对概念存在微妙的误解。

您只能创建一个 class 作为那个 class。也就是说,您不能编写 new Payable 并以某种方式期望创建任何 InvoiceSalariedEmployee object。

但是您可以引用 Payable 指向任何实现 Payable 的 object。这几乎就是子类型多态性的基本思想。

示例中发生的事情是创建了一个包含四个 Payable 引用的数组。这些引用还没有指向任何东西(它们是空的)并且还没有 InvoiceSalariedEmployee object,只有数组 object.

然后,代码创建两个 object 并将它们分配给两个引用。这与数组元素是自变量一样有效。 (几乎,但差异是由于数组协方差,这在这一点上并不重要。)特别是, new 运算符的结果在第一种情况下具有类型 Invoice ,而不是 Payable。您可以将 Invoice 分配给 Payable 引用,但转换发生在分配时,而不是创建时。

从技术上讲,您的标题问题的答案是 "no, objects are always created as the type you specify in the new expression, but you can convert the references afterwards"。

对于你的第一个问题:是的,如果不是这样,你会得到一个编译器错误。

第二种情况,以ListMap为例。看下面的例子。我们声明了一个列表,但根据标志,我们希望这个特定的 List 表现不同,因为它代表不同的 class

public class BookList{
    List <String> list;

    public BookList(boolean flag) {
        if(flag) {
            list = new ArrayList<>();
        } else {
            list = new LinkedList<>();
        }
    }
}

由于我们将其声明为 List,因此我们能够分配实现此 interface 的不同类型的列表。您可以非常简单地更改此 class 的用例,同时您仍然能够访问接口提供的每个方法。

这也是您的 Payable 数组所做的。你想将不同类型的class赋值到这个数组中,它们都实现了这个接口。

这将使为此特定接口创建方法变得更加容易。以求和法为例。

public int sumPayable(Payable[] payables) {
    int sum = 0;
    for(Payable p : payables) {
        sum += p.getPaymentAmount();
    }
    return sum;
}

在这种情况下,实现 Payable 的每个 class 的实际 class 是什么并不重要,因为您可以简单地传递一个数组,就像您创建的那样,使用此方法。