2

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?
scott
  • 1,557
  • 3
  • 15
  • 31
  • 3
    1. yes, you would get a compiler error if it wasn´t the case. 2. yes, take the `List` or `Map` as example, where you should allways declare a variable as `List` or `Map` to be able to change the assgning classtype. Your general usecase here is, that you only want to invoke the methods provided by this specific interface. – SomeJavaGuy Nov 19 '15 at 09:21
  • Thank you @KevinEsche. Please post it as an answer, and I will accept it. – scott Nov 19 '15 at 09:22
  • Yes, this is the whole point of polymorphism. – Peter Lawrey Nov 19 '15 at 10:01

2 Answers2

4

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".

Sebastian Redl
  • 69,373
  • 8
  • 123
  • 157
1

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.

SomeJavaGuy
  • 7,307
  • 2
  • 21
  • 33
  • Thank you @Kevin. I haven't come across this `` operator yet. What is it used for, and what is it called as? If you can give me a term to look up, I would google it. – scott Nov 19 '15 at 10:13
  • 1
    @scott these are [Generics](https://docs.oracle.com/javase/tutorial/java/generics/why.html) – SomeJavaGuy Nov 19 '15 at 10:15