3

I have been doing a lot of reading about polymorphism, inheritance and typing (specifically how it applies to Java).

I have seen some interesting examples, but not much explanation as to why.

I.e.:

    Person p = new Student();

I am assuming we have a Person class and a Student class which extends the Person class.

My question is: Why would you want to do this kind of assignment at all?

3 Answers 3

1

Using something like that, we can have many different types that all support the interface of Person, which means we can write code that takes a Person and doesn't care which specific type it is, as long as it supports whatever a Person supports.

You might not anticipate an AncientZombieLord class when first writing some generic code that takes a Person, but if AncientZombieLord is a subtype of Person, all the code written for a Person will work for AncientZombieLord too.

If you take a look at Java's collections, there are ArrayList and LinkedList types, which are both subtypes of List. They have different performance characteristics, but both support a common interface, so I can write code that uses a List that will work with either kind of list.

You can use this sort of thing to write a generic algorithm that uses one type now, and then switch it to something else without needing to fiddle with a lot of code -- just change one type.

In general, being able to abstract away from details that don't matter is a big win.

2
  • I get what you are saying, but if the AncientZombieLord extends Person, can't we just assign it AZL bob = new AZL(); and it would still work anywhere a Person is required? What would be gained by Person a = new AZL();?
    – lext01
    Oct 5, 2014 at 4:07
  • 1
    There is no gain by polymorphism in this kind of assignment. The benefit occurs only when you pass such an object to a method call, or return it to your caller, etc. Then you can write future-proof APIs, use old frameworks with new types, reason about things in the simplest possible way, etc. The line with the new in it must know about the specific type type anyway, so there's no point trying to hide it away on the LHS. Oct 5, 2014 at 7:30
8

The contrived examples traditionally given in such problems don't properly capture the reasoning of why polymorphism is good and useful.

Lets instead look at real world examples that are found in the Collections framework of Java. Things that implement List. Of the "All Known Implementing Classes", there are two that are most interesting for this example - the LinkedList and the ArrayList.

The LinkedList is backed by a linked list, and the ArrayList is backed by an array. These structures have different advantages and disadvantages for doing certain operations. An ArrayList is very fast for finding the arbitrary nth element, while the LinkedList is slow for this. On the other hand, sticking an element at the front or end of a LinkedList is always quite fast, while the ArrayList putting an element at the front is painfuly slow and the end can be quite bad too if it needs to grow the array.

So, there's a reason why I would chose one implementation or the other. Now, if I am returning a value from a function... ArrayList<Integer> foo() it would mean that I could never change the implementation behind it. If I later decide that I want a LinkedList - I couldn't do that because it would cause all the code that uses it to break and have to be changed to a LinkedList<Integer> instead.

Instead, I can say "it doesn't matter what list I give you - you don't need to know how I'm implementing it." And instead just give you a List<Integer> foo() method instead. Do you need to know if its a LinkedList? or ArrayList? Nope. If all I care about is giving you back a List (a collection of elements in some order that may contain duplicates), thats what you're getting. It makes it easier for me and you to know less about the implementation.

This is part of the Principle of Least Knowledge that is a component of the Law of Demeter. If I you don't need to know about it, I shouldn't tell you about it. It prevents you from reaching through the interface to the underlying implementation and assuming things about how it works.

In your example, you've got a Person and that interface (or abstract class) is all that you need to work with to do what you need to do. It allows looser coupling and more flexibility in the design later, and that is a good thing.

There are static analysis tools that can help you write code that is more in line with these guidelines. One such example is that of pmd. In its type rules, there is the loose coping rule which will give warnings like: "Avoid using implementation types (i.e., HashSet); use the interface (i.e, Set) instead" - and that is good advice. (Related SO question on the warning: Why should the interface for a Java class be prefered?)

0

@MichaelT's answer is excellent from the theory side, but here's a more concrete explanation:

In this use case, which is only one example of dynamic typing, the benefit isn't obvious just looking at the single line of code in your example. Suppose Person is an interface, abstract class or even concrete base class in which a talk() method is exposed. By declaring a Student instance as a Person, functions can accept a generic type (i.e. Person), knowing that when the code runs, it will be the Student's talk() method that is executed, not whatever might be in Person (if it even defines a method body).

abstract class Person {
  void talk() {
    System.out.println("I am a person."); // default behavior
  }
}

class Student extends Person {
  @Override
  void talk() {
    System.out.println("I am a student.");
  }
}

// Elsewhere...
public static void main(String[] args) {
    Person p = new Student();
    p.talk();
}

// Output:
I am a student.

In this manner, it is possible to have multiple implementations of the same conceptual method, without having to resort to instanceof-based switches or if/else logic.

For a more complete understanding of dynamic typing, investigate how a fully dynamically-typed language such as JavaScript works, or look at C#'s dynamic keyword and usage.

1
  • and this way of choosing which version of the method to execute is called dynamic binding.
    – bigstones
    Oct 5, 2014 at 9:02

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.