Logout

Home OOP Option Last Next

D.2.6

Explain the advantages of polymorphism.

 

Teaching Note:

For example, an action in a child object may choose to override actions of a parent object. This allows an external program to use the same action on a family of objects without knowing the implementation detail.

 

Sample Question:

----

Q1. Outline the advantages of polymorphism, using the Xyz class as an example.
----

sdfsdfsf

JSR Notes:

The first thing to note here is that if you stick to the simple cases of overloaded constructors and overriding toString( ) - which are classic, easy examples of polymorphism - you are left a bit underwhelmed. Neither seems to be that big of a deal, certainly compared to the other "big two" OOP features, encapsulation and inheritance. So you really do need to get to the point of understanding what is behind the Teaching Note's reference to "using the same action on a family of objects without knowing the implementation detail" (see the Advantage subsection #2B below).

1. Overloading & Advantages
(including overloaded constructors)

Recall that there are indeed two general examples of polymorphism: overloading, and overriding.

Overloading is when the same method name is used more than once within the same class, and this is possible because each of the similarly name methods has a unique signature, due to each having a unique parameter list.

Overloaded Constructors - This is the most common example of overloading. Quite often, one or more constructors beyond the default - no parameters - constructor are made. Taking this approach, objects of that class can then be made different ways depending on the data available to be sent from the user class during instantiation. Note that sometimes some or all default values will do fine, and other times we'll want to set them at the time of instantiation. Look back at D.2.3 for examples of this.

To reiterate, you know it's "overloading" because there are two or more methods in the same class with the same name (but different parameter lists).

Advantage of Overloading

To be clear about the advantages of overloading constructors: it adds to flexibility in the way that objects of the class can be made/instantiated, depending on the data available at the time of instantiation, and/or the variable necessity to change default values of data attributes.


2. Overriding & Advantages

Overriding in General

Recall that overriding is where one child sub-class totally overrides a method found above it in the inheritance chain. So the same exact spelling and in fact same order and number of parameters can have different results depending on which class it is called from.

You know it's "overriding" when it's a method with the same name as another method in one of the classes above it or to its side in an inheritance hierarchy. So, putting it another way, it is "re-doing" a particular method, with the exact same signature, at a lower, or the same level of a particular inheritance hierarchy.


2A. Advantages of Overriding toString( )

Overriding toString( ), which is originally defined in the Object class, is the most common example of this, and it is generally expected that it will always be overridden, so that it offers users of that class a way to see a string representation of the data it works with.

Refer back to D.2.3, but here is another example of overriding toString() at two levels of the same hierarchy.

public class Car{
    private String name = "not set yet";
private String color = "black"; public Car(String name, String color){ this.name = name;
this.color = color; } //gets and sets... public String toString(){ //overridden the Object implementation of toString() return "All the car details are: " + name + " " + color + "."; } }
In the above class, toString() is overridden from its Object class implementation. Next we see further polymorphic overriding of the toString() method in a sub-class of the above class.
public class SportsCar extends Car{
    private boolean hasSpoiler = false;
    
    public SportsCar(String name, String color, boolean hasSpoiler){
        super(name, color);
        this.hasSpoiler = hasSpoiler;

    }
    //gets and sets...
    public String toString(){ //overriden the Car implementation of toString()
        return "All the sports car details are: " + name + " " + color + "that it has a spoiler is " + hasSpoiler + ".";
}

So in terms of the advantages that toString() being overriden, it's mainly the idea that it can be expected that all classes can show a string outputted representation of the data the work with, which is useful to see to know what data the class works with.

 

2B. Advantage of Other Overriding through an Ineritance Hierarchy

As the Teaching Note puts it: "this allows an external program to use the same action on a family of objects without knowing the implementation detail." So specifically, this is practice of using a loop to iterate through an array of different objects from the same inheritance hierarchy (or "family"), allowing runtime decisions about which particular overridden method to use for each object. And this really is very useful indeed. Here's a copy and paste from the full example of this given back in D.2.3:

public class MainForMarket{
    public static void main(String[] args){
        MarketItem [] items = new MarketItem[2];
        items[0] = new FoodItem("Celery", 20);
        items[1] = new LuxuryItem("Caviar", 300);
		double totalBill = 0;
        for(int i = 0; i < items.length; i++){
            totalBill += items[i].calculateCheckoutCost();            
            //When this program runs the correct overriden methods will each be executed.
            //Actually, in this example we know items[0] is a FoodItem and items[1] a Luxury
            //item at compile time, but look below for a runtime decision situation.
        }
       System.out.println("Your total bill is " + totalBill.)
    }
}

From the example above, recall how the array of MarketItem objects is actually different objects of various classes below MarketItem in the inheritance hierarchy. And so each one of the items array has different version of calculateCheckoutCost() bound to it.

So, back to the advantage, yes, that's a pretty powerful feature of a programming language: runtime decisions based on how objects get declared during a particular running of the program. Cool.

 

3. The General Advantage of
Consistent Naming of Similar Methods

In a sentence, the advantage is that you can keep the same name for similar, yet slightly different methods.

So firstly, taking the example of overloaded constructors, all constructors for a certain class can be called the same thing - the name of the class - even though they operate differently with their different list of parameters.

And in the case of overriding of inherited methods, such as toString(), the same name can be used for similar, yet slightly different, methods. 

By keeping consistency of naming in this way, other programmers can get a hint as to the functionality of a method by recognizing the name. The assumption can be made that the overridden methods with names we recognize will have certain functionality based on the familiar name.

 

A Couple of Interesting Related Points

Consistency of Instance Variable/Parameter Names

Interestingly, a preference to keep similar methods named the same reflects the way that most Java programmers prefer to use the same name for both parameters and the internal attributes that they get assigned to. We would prefer to call, for example, a student's name studentName, whether it be the name being received as a parameter, or the attribute it gets assigned to. "studenName" is the perfect identifier, so why change it for one of those two variables. (And you'll recall we solve the potential mixing up of the two with the "this." clarification.)

So it's kind of the same with "toString( )", for example. The toString( ) method returns a String representation of an object, so when coming up with a specific representation of an object of a particular class, why make a method by some other name? "toString" is perfect. And all programmers familiar with Java will know what to expect from it, through the particular implementation.

"Overloaded" Operators

If fact, a bit more about polymorphism will help reinforce this desire to have consistent terms and so on. Using operators in various ways, depending on the kind of operand(s) being worked with, can be, in fact, seen as another example of polymorphism. The + operator in-between two integers works one way (arithmetically adding them together), but another way in-between two strings (it concatenates them together). These are different, yet similar uses, so we prefer to have only one operator, in this case +, used dependent on the context.

System.out.println(2 + 4); //Output: 6         
System.out.println("Hello" + "world"); //Output: Helloworld

 

 

In Summary, Back to the Assessment Statement:
Explain the advantages of polymorphism.

(Beyond just overloaded constructors) polymorphism allows an external "main" class to use the same named method on all subclasses, with each subclass' implementation of the polymorphic method remaining unique.