简体   繁体   中英

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

As I proceed through my online tutorial, I came across this lesson. I have an interface and two classes that implements that interface.

public interface Payable {
double getPaymentAmount();
}

and

  • class Invoice that implements the above interface Payable
  • class SalariedEmployee that extends an abstract class Employee which implements Payable interface.
  • A test class that contains the main method to test this.

Now in the test class, when creating an array of objects, the type of object was referred to as Payable[] rather than SalariedEmployee[] or Invoice[] , like

    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);
  • Is this because all the classes implements the interface Payable[] ?
  • If an interface is defined at the top level hierarchy, is it always possible to create objects of all the classes that implements that interface?

Your question title is not grammatical, but the word choice suggests there's a subtle misunderstanding of concepts going on.

You can only create a class as that class. That is, you can't write new Payable and somehow expect there to be any Invoice or SalariedEmployee objects being created.

But you can make a reference to a Payable point to any object that implements Payable . That's pretty much the fundamental idea of subtype polymorphism.

What's going on in the example is that an array of four Payable references is created. These references don't yet point at anything (they're null) and there are no Invoice or SalariedEmployee objects around yet, only the array object.

Then, the code creates two objects and assigns them to two of the references. This works the same as if the array elements were independent variables. (Almost, but the difference is due to array covariance, which isn't important at this point.) In particular, the result of the new operator has the type Invoice in the first case, not Payable . You can assign the Invoice to the Payable reference, but the conversion happens at assignment, not at creation.

So technically, the answer to your title question is "no, objects are always created as the type you specify in the new expression, but you can convert the references afterwards".

for your first question: yes, you would get a compiler error if it wasn´t the case.

for the second case, take the List or the Map as an example. Look at the following example. We declare a list but depending on the the flag, we want the this specific List to act different, since it represents a different class

public class BookList{
    List <String> list;

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

Since we declared it just as List we are able to assign different type of lists that implement this interface . You could change the usecase of this class very simple, while you are still able to acces every method that is provided by the interface.

That´s what your array of Payable is doing aswell. You want to assign different types of classes into this array, which all implement this interface.

This would make it more easy, to create methods for this specific interface. Take a summing method as an example for your case.

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

In this case, it wouldn´t matter what the actuall class of each of this classes that do implements Payable is, since you could simply pass an array, like you did create, to this method.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM