Polymorphism vs Overriding vs Overloading
Asked Answered
S

21

377

In terms of Java, when someone asks:

what is polymorphism?

Would overloading or overriding be an acceptable answer?

I think there is a bit more to it than that.

IF you had a abstract base class that defined a method with no implementation, and you defined that method in the sub class, is that still overridding?

I think overloading is not the right answer for sure.

Stipitate answered 30/9, 2008 at 19:29 Comment(1)
Below answers explains very well about polymorphism. But i have strong objection to say overloading is a type of polymorphism, which i tried justify in my question and answer that actually concentrates on overloading is polymorphism or not. I tried to justify @The Digital Gabeg answer present in this thread. Refer Elaboration: Method overloading is a static/compile-time binding but not polymorphism. Is it correct to correlate static binding with polymorphism?Pearcy
M
950

The clearest way to express polymorphism is via an abstract base class (or interface)

public abstract class Human{
   ...
   public abstract void goPee();
}

This class is abstract because the goPee() method is not definable for Humans. It is only definable for the subclasses Male and Female. Also, Human is an abstract concept — You cannot create a human that is neither Male nor Female. It’s got to be one or the other.

So we defer the implementation by using the abstract class.

public class Male extends Human{
...
    @Override
    public void goPee(){
        System.out.println("Stand Up");
    }
}

and

public class Female extends Human{
...
    @Override
    public void goPee(){
        System.out.println("Sit Down");
    }
}

Now we can tell an entire room full of Humans to go pee.

public static void main(String[] args){
    ArrayList<Human> group = new ArrayList<Human>();
    group.add(new Male());
    group.add(new Female());
    // ... add more...

    // tell the class to take a pee break
    for (Human person : group) person.goPee();
}

Running this would yield:

Stand Up
Sit Down
...
Miseno answered 30/9, 2008 at 20:33 Comment(11)
@yuudachi. I came up with this example when teaching a class. The canonical "Bank Account" class didn't really express the "abstractness" of the base class. The other canonical example (Animal, make noise) was too abstract for understanding. I was looking for a single base with too obvious subclasses. Actually, goPee() was the only example I came up with that wasn't sexist or stereotypical. (although in class, I printed "down the hall on the left" instead of stand up or sit down.)Miseno
I think it's important to point out that it's only polymorphism because which version of goPee() to call can only be determined at runtime. While this example implies that, it is nice to point out why exactly that is polymorphism. Also, it doesn't require sibling classes. It can be a parent-child relationship as well. Or even completely unrelated classes which coincidentally have the same function. An example of this can be the .toString() function. Which can be called randomly on any object, but the compiler can never know exactly which type of object.Soap
... unless specified, obviously.Soap
@Tor Valamo - whether polymorphism must be resolved at run-time seems to depend to some degree on context and whose definitions you're using. For example, early binding (overloading) is also sometimes called "compile-time polymorphism", and templates in C++ can be considered another compile-time polymorphism mechanism.Strawser
@AndrewDalke, what if the OOP principle was explained with Cat and Dog classes which are subclasses of Animal abstract class? Would that mean that mouse is not an animal because of that?Gestapo
Then comes the GDPR stating companies should not remember human pees standing up or down.Spirituel
is there any other example of runtime polymorphism in java except for overriding ?Kosiur
This is literally the best example one could ask forKeikokeil
can you mention why annotate with @override? we are not overriding right?we are implementing a definition.Respect
@Respect The override annotation can be used for not just overriding but also implementing in Java, and it's advisable to do so. The reason is that if the method in the superclass or interface (regardless of whether it's a concrete implementation, abstract class or part of an interface definition) has its signature changed or is removed, the compiler will show an error for the annotated methods. And conversely if you put the annotation on a method but made some subtle mistake in its signature (typo, arguments, exceptions) the compiler will notice. It prevents mistakes at compile-time.Rioux
I was going to say the explanation is great, but I didn't think the example itself was. Simply because men don't have to stand up to pee. We just choose to because it's quicker, and less effort (or we're at a urinal). So I don't think it's a necessary distinction to make, and therefore not a great example of needing to provide different logic for the subclasses. But then I read your comment where you said your original example used directions to the appropriate bathroom, rather than sit down/stand up. Now I'm like, this a good example 👍 (I guess I'd suggest using that differentiation though)Pepsinogen
M
105

Polymorphism is the ability of a class instance to behave as if it were an instance of another class in its inheritance tree, most often one of its ancestor classes. For example, in Java all classes inherit from Object. Therefore, you can create a variable of type Object and assign to it an instance of any class.

An override is a type of function which occurs in a class which inherits from another class. An override function "replaces" a function inherited from the base class, but does so in such a way that it is called even when an instance of its class is pretending to be a different type through polymorphism. Referring to the previous example, you could define your own class and override the toString() function. Because this function is inherited from Object, it will still be available if you copy an instance of this class into an Object-type variable. Normally, if you call toString() on your class while it is pretending to be an Object, the version of toString which will actually fire is the one defined on Object itself. However, because the function is an override, the definition of toString() from your class is used even when the class instance's true type is hidden behind polymorphism.

Overloading is the action of defining multiple methods with the same name, but with different parameters. It is unrelated to either overriding or polymorphism.

Mooncalf answered 30/9, 2008 at 19:51 Comment(8)
This is old but Polymorphism doesn't imply that the other class must be in the inheritance tree. It does in Java if you consider interfaces to be part of the inheritance tree, but not in Go, where interfaces are implemented implicitly.Ringler
Actually, you don't need classes for polymorphism at all.Lotuseater
I'm a newbie, and correct me if I'm wrong, but I wouldn't say overloading is unrelated to polymorphism. At least in Java, polymorphism is when the implementation is chosen based on the type of the caller, and overloading is when the implementation is chosen based on the type of the parameters, isn't it? Seeing the similarity between the two helps me understand it.Guardrail
Incorrect. Ad hoc polymorphism is what you described in your Overloading section and is a case of polymorphism.Sectary
"It is unrelated to either overriding or polymorphism". This statement is wrong.Dynamite
As I understand, static polymorphism same to overloading. can you clarify plz.Eveleen
I think overloading is a case of polymorphism.Archie
Ad hoc polymorphism is a authors view that came even to wikipedia. But java doc stays away from that and mentions only about polymorphism and if you open javadoc section of method overloading it is nowhere mentioned it is ad hoc polymorphism. It is a common sense for people who has depth understanding of polymorphism and the understanding of polymorphism forces them not to correlate this ad hoc concept to polymorphism.Pearcy
E
64

Polymorphism means more than one form, same object performing different operations according to the requirement.

Polymorphism can be achieved by using two ways, those are

  1. Method overriding
  2. Method overloading

Method overloading means writing two or more methods in the same class by using same method name, but the passing parameters is different.

Method overriding means we use the method names in the different classes,that means parent class method is used in the child class.

In Java to achieve polymorphism a super class reference variable can hold the sub class object.

To achieve the polymorphism every developer must use the same method names in the project.

Eyecup answered 21/10, 2012 at 5:7 Comment(3)
+1 for nice answer. The accepted answer only explains one type of polymorphism. This answer is complete.Tedder
polymorphism is a paradigm (OOP), but overriding & overloading are language facilities.Beckwith
Polymorphism can also be achieved by generic type.Archie
C
46

Both overriding and overloading are used to achieve polymorphism.

You could have a method in a class that is overridden in one or more subclasses. The method does different things depending on which class was used to instantiate an object.

    abstract class Beverage {
       boolean isAcceptableTemperature();
    }

    class Coffee extends Beverage {
       boolean isAcceptableTemperature() { 
           return temperature > 70;
       }
    }

    class Wine extends Beverage {
       boolean isAcceptableTemperature() { 
           return temperature < 10;
       }
    }

You could also have a method that is overloaded with two or more sets of arguments. The method does different things based on the type(s) of argument(s) passed.

    class Server {
        public void pour (Coffee liquid) {
            new Cup().fillToTopWith(liquid);
        }

        public void pour (Wine liquid) {
            new WineGlass().fillHalfwayWith(liquid);
        }

        public void pour (Lemonade liquid, boolean ice) {
            Glass glass = new Glass();
            if (ice) {
                glass.fillToTopWith(new Ice());
            }
            glass.fillToTopWith(liquid);
        }
    }
Carhart answered 30/9, 2008 at 19:42 Comment(4)
I suppose it was voted down because historically method overloading is not considered as part of polymorphism in the object oriented paradigm. Method overloading and polymorphism are two ortogonal, independent features of a programming language.Dolce
As I stated in my answer here, I disagree -- the two features are not orthogonal, but are closely related. Polymorphism != Inheritance. You have my up-vote.Loralyn
In other words, type polymorphism vs. ad-hoc polymorphism. I'm upvoting this answer, even if not as complete as it should, because it correctly states that both overloading and overriding are related to polymorphism. Saying that polymorphism in OOP languages can only be achieved by class inheritance is simply wrong - we should remember that there are some other OOP languages besides Java and C++, where one can use concepts like multiple dispatching, ad hoc polymorphism, parametric polymorphism and so on.Handsomely
@Handsomely This might be incomplete but it answers the question much better than the rest IMHO. Also, very nice that you mentioned the ad-hoc and parametric polymorphism.Tenement
C
42

Here's an example of polymorphism in pseudo-C#/Java:

class Animal
{
    abstract string MakeNoise ();
}

class Cat : Animal {
    string MakeNoise () {
        return "Meow";
    }
}

class Dog : Animal {
    string MakeNoise () {
        return "Bark";
    }
}

Main () {
   Animal animal = Zoo.GetAnimal ();
   Console.WriteLine (animal.MakeNoise ());
}

The Main function doesn't know the type of the animal and depends on a particular implementation's behavior of the MakeNoise() method.

Edit: Looks like Brian beat me to the punch. Funny we used the same example. But the above code should help clarify the concepts.

Cracked answered 30/9, 2008 at 19:41 Comment(4)
It's an example of runtime polymorphism. Compile time polymorphism is also possible through method overloading and generic types.Agrobiology
Shape -> Parallelogram -> Rectangle -> SquareIams
@yankee2905 in this case, I think you could use interfaces, since a class could implement multiple interfaces.Malissa
@Zhisheng Or adding an pee method in abstract parent class? I would use interface to implement something else.Kelsey
M
16

You are correct that overloading is not the answer.

Neither is overriding. Overriding is the means by which you get polymorphism. Polymorphism is the ability for an object to vary behavior based on its type. This is best demonstrated when the caller of an object that exhibits polymorphism is unaware of what specific type the object is.

Meath answered 30/9, 2008 at 19:35 Comment(2)
It should not be the behaviour of the object that changes, but his implementation. Same behaviour, different implementation, that's polymorphism.Roadhouse
@Roadhouse You need to define behaviour, especially the adjective same. If the behaviour is same, why should their implementation be different? It is not that someone is unhappy with a certain implementation, hence requires a different one.Atreus
L
12

Specifically saying overloading or overriding doesn't give the full picture. Polymorphism is simply the ability of an object to specialize its behavior based on its type.

I would disagree with some of the answers here in that overloading is a form of polymorphism (parametric polymorphism) in the case that a method with the same name can behave differently give different parameter types. A good example is operator overloading. You can define "+" to accept different types of parameters -- say strings or int's -- and based on those types, "+" will behave differently.

Polymorphism also includes inheritance and overriding methods, though they can be abstract or virtual in the base type. In terms of inheritance-based polymorphism, Java only supports single class inheritance limiting it polymorphic behavior to that of a single chain of base types. Java does support implementation of multiple interfaces which is yet another form of polymorphic behavior.

Loralyn answered 30/9, 2008 at 19:51 Comment(6)
You're right in terms of what the words involved mean in general, but in a programming context, when people say "polymorphism" they always means "inheritance-based polymorphism". Interesting point, but I think that describing polymorphism this way will confuse people.Mooncalf
It may be easier to explain polymorphism in terms of inheritance alone, but the way this particular question was asked I think it's prudent to describe parametric polymorphism as well.Carhart
To be clear, I think the different forms should be stated -- which I haven't even adequately done -- because there are a few answers here that are presented as absolute. I respectfully disagree that in "programmer context ... 'polymorphism' always means 'inheritance-based polymorphism'"Loralyn
i think overloading is better categorized as Ad-hoc_polymorphism en.wikipedia.org/wiki/…Hammertoe
I tend to agree with 'The Digital Gabeg' on following. If you are discussing OOP, polymorphism usually means subtype polymorphism, and if you are discussing about type theory it means any type of polymorphism.but like you say, with 'programmer context' it's too ambiguous to deride.Hammertoe
+1 for " Polymorphism is simply the ability of an object to specialize its behavior based on its type."; that a subclass may override a method that provides more specific behaviour for the subclass and that the runtime knows which method to invoke based on the type of the object which it has.Seaware
I
8

Although, Polymorphism is already explained in great details in this post but I would like to put more emphasis on why part of it.

Why Polymorphism is so important in any OOP language.

Let’s try to build a simple application for a TV with and without Inheritance/Polymorphism. Post each version of the application, we do a small retrospective.

Supposing, you are a software engineer at a TV company and you are asked to write software for Volume, Brightness and Colour controllers to increase and decrease their values on user command.

You start with writing classes for each of these features by adding

  1. set:- To set a value of a controller.(Supposing this has controller specific code)
  2. get:- To get a value of a controller.(Supposing this has controller specific code)
  3. adjust:- To validate the input and setting a controller.(Generic validations.. independent of controllers)
  4. user input mapping with controllers :- To get user input and invoking controllers accordingly.

Application Version 1

import java.util.Scanner;    
class VolumeControllerV1 {
    private int value;
    int get()    {
        return value;
    }
    void set(int value) {
        System.out.println("Old value of VolumeController \t"+this.value);
        this.value = value;
        System.out.println("New value of VolumeController \t"+this.value);
    }
    void adjust(int value)  {
        int temp = this.get();
        if(((value > 0) && (temp >= 100)) || ((value < 0) && (temp <= 0)))    {
            System.out.println("Can not adjust any further");
            return;
        }
        this.set(temp + value);
    }
}
class  BrightnessControllerV1 {
    private int value;
    int get()    {
        return value;
    }
    void set(int value) {
        System.out.println("Old value of BrightnessController \t"+this.value);
        this.value = value;
        System.out.println("New value of BrightnessController \t"+this.value);
    }
    void adjust(int value)  {
        int temp = this.get();
        if(((value > 0) && (temp >= 100)) || ((value < 0) && (temp <= 0)))    {
            System.out.println("Can not adjust any further");
            return;
        }
        this.set(temp + value);
    }
}
class ColourControllerV1    {
    private int value;
    int get()    {
        return value;
    }
    void set(int value) {
        System.out.println("Old value of ColourController \t"+this.value);
        this.value = value;
        System.out.println("New value of ColourController \t"+this.value);
    }
    void adjust(int value)  {
        int temp = this.get();
        if(((value > 0) && (temp >= 100)) || ((value < 0) && (temp <= 0)))    {
            System.out.println("Can not adjust any further");
            return;
        }
        this.set(temp + value);
    }
}

/*
 *       There can be n number of controllers
 * */
public class TvApplicationV1 {
    public static void main(String[] args)  {
        VolumeControllerV1 volumeControllerV1 = new VolumeControllerV1();
        BrightnessControllerV1 brightnessControllerV1 = new BrightnessControllerV1();
        ColourControllerV1 colourControllerV1 = new ColourControllerV1();


        OUTER: while(true) {
            Scanner sc=new Scanner(System.in);
            System.out.println(" Enter your option \n Press 1 to increase volume \n Press 2 to decrease volume");
            System.out.println(" Press 3 to increase brightness \n Press 4 to decrease brightness");
            System.out.println(" Press 5 to increase color \n Press 6 to decrease color");
            System.out.println("Press any other Button to shutdown");
            int button = sc.nextInt();
            switch (button) {
                case  1:    {
                    volumeControllerV1.adjust(5);
                    break;
                }
                case 2: {
                    volumeControllerV1.adjust(-5);
                    break;
                }
                case  3:    {
                    brightnessControllerV1.adjust(5);
                    break;
                }
                case 4: {
                    brightnessControllerV1.adjust(-5);
                    break;
                }
                case  5:    {
                    colourControllerV1.adjust(5);
                    break;
                }
                case 6: {
                colourControllerV1.adjust(-5);
                break;
            }
            default:
                System.out.println("Shutting down...........");
                break OUTER;
        }

    }
    }
}

Now you have our first version of working application ready to be deployed. Time to analyze the work done so far.

Issues in TV Application Version 1

  1. Adjust(int value) code is duplicate in all three classes. You would like to minimize the code duplicity. (But you did not think of common code and moving it to some super class to avoid duplicate code)

You decide to live with that as long as your application works as expected.

After sometimes, your Boss comes back to you and asks you to add reset functionality to the existing application. Reset would set all 3 three controller to their respective default values.

You start writing a new class (ResetFunctionV2) for the new functionality and map the user input mapping code for this new feature.

Application Version 2

import java.util.Scanner;
class VolumeControllerV2    {

    private int defaultValue = 25;
    private int value;

    int getDefaultValue() {
        return defaultValue;
    }
    int get()    {
        return value;
    }
    void set(int value) {
        System.out.println("Old value of VolumeController \t"+this.value);
        this.value = value;
        System.out.println("New value of VolumeController \t"+this.value);
    }
    void adjust(int value)  {
        int temp = this.get();
        if(((value > 0) && (temp >= 100)) || ((value < 0) && (temp <= 0)))    {
            System.out.println("Can not adjust any further");
            return;
        }
        this.set(temp + value);
    }
}
class  BrightnessControllerV2   {

    private int defaultValue = 50;
    private int value;
    int get()    {
        return value;
    }
    int getDefaultValue() {
        return defaultValue;
    }
    void set(int value) {
        System.out.println("Old value of BrightnessController \t"+this.value);
        this.value = value;
        System.out.println("New value of BrightnessController \t"+this.value);
    }
    void adjust(int value)  {
        int temp = this.get();
        if(((value > 0) && (temp >= 100)) || ((value < 0) && (temp <= 0)))    {
            System.out.println("Can not adjust any further");
            return;
        }
        this.set(temp + value);
    }
}
class ColourControllerV2    {

    private int defaultValue = 40;
    private int value;
    int get()    {
        return value;
    }
    int getDefaultValue() {
        return defaultValue;
    }
    void set(int value) {
        System.out.println("Old value of ColourController \t"+this.value);
        this.value = value;
        System.out.println("New value of ColourController \t"+this.value);
    }
    void adjust(int value)  {
        int temp = this.get();
        if(((value > 0) && (temp >= 100)) || ((value < 0) && (temp <= 0)))    {
            System.out.println("Can not adjust any further");
            return;
        }
        this.set(temp + value);
    }
}

class ResetFunctionV2 {

    private VolumeControllerV2 volumeControllerV2 ;
    private BrightnessControllerV2 brightnessControllerV2;
    private ColourControllerV2 colourControllerV2;

    ResetFunctionV2(VolumeControllerV2 volumeControllerV2, BrightnessControllerV2 brightnessControllerV2, ColourControllerV2 colourControllerV2)  {
        this.volumeControllerV2 = volumeControllerV2;
        this.brightnessControllerV2 = brightnessControllerV2;
        this.colourControllerV2 = colourControllerV2;
    }
    void onReset()    {
        volumeControllerV2.set(volumeControllerV2.getDefaultValue());
        brightnessControllerV2.set(brightnessControllerV2.getDefaultValue());
        colourControllerV2.set(colourControllerV2.getDefaultValue());
    }
}
/*
 *       so on
 *       There can be n number of controllers
 *
 * */
public class TvApplicationV2 {
    public static void main(String[] args)  {
        VolumeControllerV2 volumeControllerV2 = new VolumeControllerV2();
        BrightnessControllerV2 brightnessControllerV2 = new BrightnessControllerV2();
        ColourControllerV2 colourControllerV2 = new ColourControllerV2();

        ResetFunctionV2 resetFunctionV2 = new ResetFunctionV2(volumeControllerV2, brightnessControllerV2, colourControllerV2);

        OUTER: while(true) {
            Scanner sc=new Scanner(System.in);
            System.out.println(" Enter your option \n Press 1 to increase volume \n Press 2 to decrease volume");
            System.out.println(" Press 3 to increase brightness \n Press 4 to decrease brightness");
            System.out.println(" Press 5 to increase color \n Press 6 to decrease color");
            System.out.println(" Press 7 to reset TV \n Press any other Button to shutdown");
            int button = sc.nextInt();
            switch (button) {
                case  1:    {
                    volumeControllerV2.adjust(5);
                    break;
                }
                case 2: {
                    volumeControllerV2.adjust(-5);
                    break;
                }
                case  3:    {
                    brightnessControllerV2.adjust(5);
                    break;
                }
                case 4: {
                    brightnessControllerV2.adjust(-5);
                    break;
                }
                case  5:    {
                    colourControllerV2.adjust(5);
                    break;
                }
                case 6: {
                    colourControllerV2.adjust(-5);
                    break;
                }
                case 7: {
                    resetFunctionV2.onReset();
                    break;
                }
                default:
                    System.out.println("Shutting down...........");
                    break OUTER;
            }

        }
    }
}

So you have your application ready with Reset feature. But, now you start realizing that

Issues in TV Application Version 2

  1. If a new controller is introduced to the product, you have to change Reset feature code.
  2. If the count of the controller grows very high, you would have issue in holding the references of the controllers.
  3. Reset feature code is tightly coupled with all the controllers Class’s code(to get and set default values).
  4. Reset feature class (ResetFunctionV2) can access other method of the Controller class’s (adjust) which is undesirable.

At the same time, You hear from you Boss that you might have to add a feature wherein each of controllers, on start-up, needs to check for the latest version of driver from company’s hosted driver repository via internet.

Now you start thinking that this new feature to be added resembles with Reset feature and Issues of Application (V2) will be multiplied if you don’t re-factor your application.

You start thinking of using inheritance so that you can take advantage from polymorphic ability of JAVA and you add a new abstract class (ControllerV3) to

  1. Declare the signature of get and set method.
  2. Contain adjust method implementation which was earlier replicated among all the controllers.
  3. Declare setDefault method so that reset feature can be easily implemented leveraging Polymorphism.

With these improvements, you have version 3 of your TV application ready with you.

Application Version 3

import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

abstract class ControllerV3 {
    abstract void set(int value);
    abstract int get();
    void adjust(int value)  {
        int temp = this.get();
        if(((value > 0) && (temp >= 100)) || ((value < 0) && (temp <= 0)))    {
            System.out.println("Can not adjust any further");
            return;
        }
        this.set(temp + value);
    }
    abstract void setDefault();
}
class VolumeControllerV3 extends ControllerV3   {

    private int defaultValue = 25;
    private int value;

    public void setDefault() {
        set(defaultValue);
    }
    int get()    {
        return value;
    }
    void set(int value) {
        System.out.println("Old value of VolumeController \t"+this.value);
        this.value = value;
        System.out.println("New value of VolumeController \t"+this.value);
    }
}
class  BrightnessControllerV3  extends ControllerV3   {

    private int defaultValue = 50;
    private int value;

    public void setDefault() {
        set(defaultValue);
    }
    int get()    {
        return value;
    }
    void set(int value) {
        System.out.println("Old value of BrightnessController \t"+this.value);
        this.value = value;
        System.out.println("New value of BrightnessController \t"+this.value);
    }
}
class ColourControllerV3 extends ControllerV3   {

    private int defaultValue = 40;
    private int value;

    public void setDefault() {
        set(defaultValue);
    }
    int get()    {
        return value;
    }
    void set(int value) {
        System.out.println("Old value of ColourController \t"+this.value);
        this.value = value;
        System.out.println("New value of ColourController \t"+this.value);
    }
}

class ResetFunctionV3 {

    private List<ControllerV3> controllers = null;

    ResetFunctionV3(List<ControllerV3> controllers)  {
        this.controllers = controllers;
    }
    void onReset()    {
        for (ControllerV3 controllerV3 :this.controllers)  {
            controllerV3.setDefault();
        }
    }
}
/*
 *       so on
 *       There can be n number of controllers
 *
 * */
public class TvApplicationV3 {
    public static void main(String[] args)  {
        VolumeControllerV3 volumeControllerV3 = new VolumeControllerV3();
        BrightnessControllerV3 brightnessControllerV3 = new BrightnessControllerV3();
        ColourControllerV3 colourControllerV3 = new ColourControllerV3();

        List<ControllerV3> controllerV3s = new ArrayList<>();
        controllerV3s.add(volumeControllerV3);
        controllerV3s.add(brightnessControllerV3);
        controllerV3s.add(colourControllerV3);

        ResetFunctionV3 resetFunctionV3 = new ResetFunctionV3(controllerV3s);

        OUTER: while(true) {
            Scanner sc=new Scanner(System.in);
            System.out.println(" Enter your option \n Press 1 to increase volume \n Press 2 to decrease volume");
            System.out.println(" Press 3 to increase brightness \n Press 4 to decrease brightness");
            System.out.println(" Press 5 to increase color \n Press 6 to decrease color");
            System.out.println(" Press 7 to reset TV \n Press any other Button to shutdown");
            int button = sc.nextInt();
            switch (button) {
                case  1:    {
                    volumeControllerV3.adjust(5);
                    break;
                }
                case 2: {
                    volumeControllerV3.adjust(-5);
                    break;
                }
                case  3:    {
                    brightnessControllerV3.adjust(5);
                    break;
                }
                case 4: {
                    brightnessControllerV3.adjust(-5);
                    break;
                }
                case  5:    {
                    colourControllerV3.adjust(5);
                    break;
                }
                case 6: {
                    colourControllerV3.adjust(-5);
                    break;
                }
                case 7: {
                    resetFunctionV3.onReset();
                    break;
                }
                default:
                    System.out.println("Shutting down...........");
                    break OUTER;
            }

        }
    }
}

Although most of the Issue listed in issue list of V2 were addressed except

Issues in TV Application Version 3

  1. Reset feature class (ResetFunctionV3) can access other method of the Controller class’s (adjust) which is undesirable.

Again, you think of solving this problem, as now you have another feature (driver update at startup) to implement as well. If you don’t fix it, it will get replicated to new features as well.

So you divide the contract defined in abstract class and write 2 interfaces for

  1. Reset feature.
  2. Driver Update.

And have your 1st concrete class implement them as below

Application Version 4

import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

interface OnReset {
    void setDefault();
}
interface OnStart {
    void checkForDriverUpdate();
}
abstract class ControllerV4 implements OnReset,OnStart {
    abstract void set(int value);
    abstract int get();
    void adjust(int value)  {
        int temp = this.get();
        if(((value > 0) && (temp >= 100)) || ((value < 0) && (temp <= 0)))    {
            System.out.println("Can not adjust any further");
            return;
        }
        this.set(temp + value);
    }
}

class VolumeControllerV4 extends ControllerV4 {

    private int defaultValue = 25;
    private int value;
    @Override
    int get()    {
        return value;
    }
    void set(int value) {
        System.out.println("Old value of VolumeController \t"+this.value);
        this.value = value;
        System.out.println("New value of VolumeController \t"+this.value);
    }
    @Override
    public void setDefault() {
        set(defaultValue);
    }

    @Override
    public void checkForDriverUpdate()    {
        System.out.println("Checking driver update for VolumeController .... Done");
    }
}
class  BrightnessControllerV4 extends ControllerV4 {

    private int defaultValue = 50;
    private int value;
    @Override
    int get()    {
        return value;
    }
    @Override
    void set(int value) {
        System.out.println("Old value of BrightnessController \t"+this.value);
        this.value = value;
        System.out.println("New value of BrightnessController \t"+this.value);
    }

    @Override
    public void setDefault() {
        set(defaultValue);
    }

    @Override
    public void checkForDriverUpdate()    {
        System.out.println("Checking driver update for BrightnessController .... Done");
    }
}
class ColourControllerV4 extends ControllerV4 {

    private int defaultValue = 40;
    private int value;
    @Override
    int get()    {
        return value;
    }
    void set(int value) {
        System.out.println("Old value of ColourController \t"+this.value);
        this.value = value;
        System.out.println("New value of ColourController \t"+this.value);
    }
    @Override
    public void setDefault() {
        set(defaultValue);
    }

    @Override
    public void checkForDriverUpdate()    {
        System.out.println("Checking driver update for ColourController .... Done");
    }
}
class ResetFunctionV4 {

    private List<OnReset> controllers = null;

    ResetFunctionV4(List<OnReset> controllers)  {
        this.controllers = controllers;
    }
    void onReset()    {
        for (OnReset onreset :this.controllers)  {
            onreset.setDefault();
        }
    }
}
class InitializeDeviceV4 {

    private List<OnStart> controllers = null;

    InitializeDeviceV4(List<OnStart> controllers)  {
        this.controllers = controllers;
    }
    void initialize()    {
        for (OnStart onStart :this.controllers)  {
            onStart.checkForDriverUpdate();
        }
    }
}
/*
*       so on
*       There can be n number of controllers
*
* */
public class TvApplicationV4 {
    public static void main(String[] args)  {
        VolumeControllerV4 volumeControllerV4 = new VolumeControllerV4();
        BrightnessControllerV4 brightnessControllerV4 = new BrightnessControllerV4();
        ColourControllerV4 colourControllerV4 = new ColourControllerV4();
        List<ControllerV4> controllerV4s = new ArrayList<>();
        controllerV4s.add(brightnessControllerV4);
        controllerV4s.add(volumeControllerV4);
        controllerV4s.add(colourControllerV4);

        List<OnStart> controllersToInitialize = new ArrayList<>();
        controllersToInitialize.addAll(controllerV4s);
        InitializeDeviceV4 initializeDeviceV4 = new InitializeDeviceV4(controllersToInitialize);
        initializeDeviceV4.initialize();

        List<OnReset> controllersToReset = new ArrayList<>();
        controllersToReset.addAll(controllerV4s);
        ResetFunctionV4 resetFunctionV4 = new ResetFunctionV4(controllersToReset);

        OUTER: while(true) {
            Scanner sc=new Scanner(System.in);
            System.out.println(" Enter your option \n Press 1 to increase volume \n Press 2 to decrease volume");
            System.out.println(" Press 3 to increase brightness \n Press 4 to decrease brightness");
            System.out.println(" Press 5 to increase color \n Press 6 to decrease color");
            System.out.println(" Press 7 to reset TV \n Press any other Button to shutdown");
            int button = sc.nextInt();
            switch (button) {
                case  1:    {
                    volumeControllerV4.adjust(5);
                    break;
                }
                case 2: {
                    volumeControllerV4.adjust(-5);
                    break;
                }
                case  3:    {
                    brightnessControllerV4.adjust(5);
                    break;
                }
                case 4: {
                    brightnessControllerV4.adjust(-5);
                    break;
                }
                case  5:    {
                    colourControllerV4.adjust(5);
                    break;
                }
                case 6: {
                    colourControllerV4.adjust(-5);
                    break;
                }
                case 7: {
                    resetFunctionV4.onReset();
                    break;
                }
                default:
                    System.out.println("Shutting down...........");
                    break OUTER;
            }

        }
    }
}

Now all of the issue faced by you got addressed and you realized that with the use of Inheritance and Polymorphism you could

  1. Keep various part of application loosely coupled.( Reset or Driver Update feature components don’t need to be made aware of actual controller classes(Volume, Brightness and Colour), any class implementing OnReset or OnStart will be acceptable to Reset or Driver Update feature components respectively).
  2. Application enhancement becomes easier.(New addition of controller wont impact reset or driver update feature component, and it is now really easy for you to add new ones)
  3. Keep layer of abstraction.(Now Reset feature can see only setDefault method of controllers and Reset feature can see only checkForDriverUpdate method of controllers)

Hope, this helps :-)

Ingrained answered 6/5, 2018 at 17:18 Comment(0)
S
7

The classic example, Dogs and cats are animals, animals have the method makeNoise. I can iterate through an array of animals calling makeNoise on them and expect that they would do there respective implementation.

The calling code does not have to know what specific animal they are.

Thats what I think of as polymorphism.

Stipitate answered 30/9, 2008 at 19:37 Comment(0)
K
7

Polymorphism simply means "Many Forms".

It does not REQUIRE inheritance to achieve...as interface implementation, which is not inheritance at all, serves polymorphic needs. Arguably, interface implementation serves polymorphic needs "Better" than inheritance.

For example, would you create a super-class to describe all things that can fly? I should think not. You would be be best served to create an interface that describes flight and leave it at that.

So, since interfaces describe behavior, and method names describe behavior (to the programmer), it is not too far of a stretch to consider method overloading as a lesser form of polymorphism.

Kishke answered 20/12, 2010 at 5:2 Comment(1)
Definitely the best answer yet. Polymorphism can be applied to all language constructs, be it nouns (classes) or verbs (methods).Circumcise
G
6

Polymorphism is the ability for an object to appear in multiple forms. This involves using inheritance and virtual functions to build a family of objects which can be interchanged. The base class contains the prototypes of the virtual functions, possibly unimplemented or with default implementations as the application dictates, and the various derived classes each implements them differently to affect different behaviors.

Gook answered 30/9, 2008 at 19:36 Comment(0)
D
5

overloading is when you define 2 methods with the same name but different parameters

overriding is where you change the behavior of the base class via a function with the same name in a subclass.

So Polymorphism is related to overriding but not really overloading.

However if someone gave me a simple answer of "overriding" for the question "What is polymorphism?" I would ask for further explanation.

Doldrums answered 30/9, 2008 at 19:35 Comment(0)
J
4

Neither:

Overloading is when you have the same function name that takes different parameters.

Overriding is when a child class replaces a parent's method with one of its own (this in iteself does not constitute polymorphism).

Polymorphism is late binding, e.g. the base class (parent) methods are being called but not until runtime does the application know what the actual object is - it may be a child class whose methods are different. This is because any child class can be used where a base class is defined.

In Java you see polymorphism a lot with the collections library:

int countStuff(List stuff) {
  return stuff.size();
}

List is the base class, the compiler has no clue if you're counting a linked list, vector, array, or a custom list implementation, as long as it acts like a List:

List myStuff = new MyTotallyAwesomeList();
int result = countStuff(myStuff);

If you were overloading you'd have:

int countStuff(LinkedList stuff) {...}
int countStuff(ArrayList stuff) {...}
int countStuff(MyTotallyAwesomeList stuff) {...}
etc...

and the correct version of countStuff() would be picked by the compiler to match the parameters.

Jacal answered 30/9, 2008 at 19:44 Comment(0)
G
4

Q1. What is polymorphism?

From java tutorial

The dictionary definition of polymorphism refers to a principle in biology in which an organism or species can have many different forms or stages. This principle can also be applied to object-oriented programming and languages like the Java language. Subclasses of a class can define their own unique behaviors and yet share some of the same functionality of the parent class.

By considering the examples and definition, overriding should be accepted answer.

Regarding your second query:

Q2. IF you had a abstract base class that defined a method with no implementation, and you defined that method in the sub class, is that still overridding?

It should be called overriding.

Have a look at this example to understand different types of overriding.

  1. Base class provides no implementation and sub-class has to override complete method - (abstract)
  2. Base class provides default implementation and sub-class can change the behaviour
  3. Sub-class adds extension to base class implementation by calling super.methodName() as first statement
  4. Base class defines structure of the algorithm (Template method) and sub-class will override a part of algorithm

code snippet:

import java.util.HashMap;

abstract class Game implements Runnable{

    protected boolean runGame = true;
    protected Player player1 = null;
    protected Player player2 = null;
    protected Player currentPlayer = null;
    
    public Game(){
        player1 = new Player("Player 1");
        player2 = new Player("Player 2");
        currentPlayer = player1;
        initializeGame();
    }

    /* Type 1: Let subclass define own implementation. Base class defines abstract method to force
        sub-classes to define implementation    
    */
    
    protected abstract void initializeGame();
    
    /* Type 2: Sub-class can change the behaviour. If not, base class behaviour is applicable */
    protected void logTimeBetweenMoves(Player player){
        System.out.println("Base class: Move Duration: player.PlayerActTime - player.MoveShownTime");
    }
    
    /* Type 3: Base class provides implementation. Sub-class can enhance base class implementation by calling
        super.methodName() in first line of the child class method and specific implementation later */
    protected void logGameStatistics(){
        System.out.println("Base class: logGameStatistics:");
    }
    /* Type 4: Template method: Structure of base class can't be changed but sub-class can some part of behaviour */
    protected void runGame() throws Exception{
        System.out.println("Base class: Defining the flow for Game:");  
        while ( runGame) {
            /*
            1. Set current player
            2. Get Player Move
            */
            validatePlayerMove(currentPlayer);  
            logTimeBetweenMoves(currentPlayer);
            Thread.sleep(500);
            setNextPlayer();
        }
        logGameStatistics();
    }
    /* sub-part of the template method, which define child class behaviour */
    protected abstract void validatePlayerMove(Player p);
    
    protected void setRunGame(boolean status){
        this.runGame = status;
    }
    public void setCurrentPlayer(Player p){
        this.currentPlayer = p;
    }
    public void setNextPlayer(){
        if ( currentPlayer == player1) {
            currentPlayer = player2;
        }else{
            currentPlayer = player1;
        }
    }
    public void run(){
        try{
            runGame();
        }catch(Exception err){
            err.printStackTrace();
        }
    }
}

class Player{
    String name;
    Player(String name){
        this.name = name;
    }
    public String getName(){
        return name;
    }
}

/* Concrete Game implementation  */
class Chess extends Game{
    public Chess(){
        super();
    }
    public void initializeGame(){
        System.out.println("Child class: Initialized Chess game");
    }
    protected void validatePlayerMove(Player p){
        System.out.println("Child class: Validate Chess move:"+p.getName());
    }
    protected void logGameStatistics(){
        super.logGameStatistics();
        System.out.println("Child class: Add Chess specific logGameStatistics:");
    }
}
class TicTacToe extends Game{
    public TicTacToe(){
        super();
    }
    public void initializeGame(){
        System.out.println("Child class: Initialized TicTacToe game");
    }
    protected void validatePlayerMove(Player p){
        System.out.println("Child class: Validate TicTacToe move:"+p.getName());
    }
}

public class Polymorphism{
    public static void main(String args[]){
        try{
        
            Game game = new Chess();
            Thread t1 = new Thread(game);
            t1.start();
            Thread.sleep(1000);
            game.setRunGame(false);
            Thread.sleep(1000);
                        
            game = new TicTacToe();
            Thread t2 = new Thread(game);
            t2.start();
            Thread.sleep(1000);
            game.setRunGame(false);
        
        }catch(Exception err){
            err.printStackTrace();
        }       
    }
}

output:

Child class: Initialized Chess game
Base class: Defining the flow for Game:
Child class: Validate Chess move:Player 1
Base class: Move Duration: player.PlayerActTime - player.MoveShownTime
Child class: Validate Chess move:Player 2
Base class: Move Duration: player.PlayerActTime - player.MoveShownTime
Base class: logGameStatistics:
Child class: Add Chess specific logGameStatistics:
Child class: Initialized TicTacToe game
Base class: Defining the flow for Game:
Child class: Validate TicTacToe move:Player 1
Base class: Move Duration: player.PlayerActTime - player.MoveShownTime
Child class: Validate TicTacToe move:Player 2
Base class: Move Duration: player.PlayerActTime - player.MoveShownTime
Base class: logGameStatistics:
Gaye answered 16/9, 2016 at 13:37 Comment(0)
A
3

The term overloading refers to having multiple versions of something with the same name, usually methods with different parameter lists

public int DoSomething(int objectId) { ... }
public int DoSomething(string objectName) { ... }

So these functions might do the same thing but you have the option to call it with an ID, or a name. Has nothing to do with inheritance, abstract classes, etc.

Overriding usually refers to polymorphism, as you described in your question

Atalee answered 30/9, 2008 at 19:33 Comment(0)
M
3

I think guys your are mixing concepts. Polymorphism is the ability of an object to behave differently at run time. For achieving this, you need two requisites:

  1. Late Binding
  2. Inheritance.

Having said that overloading means something different to overriding depending on the language you are using. For example in Java does not exist overriding but overloading. Overloaded methods with different signature to its base class are available in the subclass. Otherwise they would be overridden (please, see that I mean now the fact of there is no way to call your base class method from outside the object).

However in C++ that is not so. Any overloaded method, independently whether the signature is the same or not (diffrrent amount, different type) is as well overridden. That is to day, the base class' method is no longer available in the subclass when being called from outside the subclass object, obviously.

So the answer is when talking about Java use overloading. In any other language may be different as it happens in c++

Mowery answered 24/2, 2012 at 12:52 Comment(0)
B
3

overriding is more like hiding an inherited method by declaring a method with the same name and signature as the upper level method (super method), this adds a polymorphic behaviour to the class . in other words the decision to choose wich level method to be called will be made at run time not on compile time . this leads to the concept of interface and implementation .

Bookshelf answered 26/4, 2013 at 12:6 Comment(0)
C
2

Polymorphism is more likely as far as it's meaning is concerned ... to OVERRIDING in java

It's all about different behavior of the SAME object in different situations(In programming way ... you can call different ARGUMENTS)

I think the example below will help you to understand ... Though it's not PURE java code ...

     public void See(Friend)
     {
        System.out.println("Talk");
     }

But if we change the ARGUMENT ... the BEHAVIOR will be changed ...

     public void See(Enemy)
     {
        System.out.println("Run");
     }

The Person(here the "Object") is same ...

Carpophore answered 11/9, 2012 at 14:4 Comment(0)
C
2

Polymorphism is a multiple implementations of an object or you could say multiple forms of an object. lets say you have class Animals as the abstract base class and it has a method called movement() which defines the way that the animal moves. Now in reality we have different kinds of animals and they move differently as well some of them with 2 legs, others with 4 and some with no legs, etc.. To define different movement() of each animal on earth, we need to apply polymorphism. However, you need to define more classes i.e. class Dogs Cats Fish etc. Then you need to extend those classes from the base class Animals and override its method movement() with a new movement functionality based on each animal you have. You can also use Interfaces to achieve that. The keyword in here is overriding, overloading is different and is not considered as polymorphism. with overloading you can define multiple methods "with same name" but with different parameters on same object or class.

Carmel answered 15/9, 2013 at 22:37 Comment(0)
M
1
import java.io.IOException;

class Super {

    protected Super getClassName(Super s) throws IOException {
        System.out.println(this.getClass().getSimpleName() + " - I'm parent");
        return null;
    }

}

class SubOne extends Super {

    @Override
    protected Super getClassName(Super s)  {
        System.out.println(this.getClass().getSimpleName() + " - I'm Perfect Overriding");
        return null;
    }

}

class SubTwo extends Super {

    @Override
    protected Super getClassName(Super s) throws NullPointerException {
        System.out.println(this.getClass().getSimpleName() + " - I'm Overriding and Throwing Runtime Exception");
        return null;
    }

}

class SubThree extends Super {

    @Override
    protected SubThree getClassName(Super s) {
        System.out.println(this.getClass().getSimpleName()+ " - I'm Overriding and Returning SubClass Type");
        return null;
    }

}

class SubFour extends Super {

    @Override
    protected Super getClassName(Super s) throws IOException {
        System.out.println(this.getClass().getSimpleName()+ " - I'm Overriding and Throwing Narrower Exception ");
        return null;
    }

}

class SubFive extends Super {

    @Override
    public Super getClassName(Super s) {
        System.out.println(this.getClass().getSimpleName()+ " - I'm Overriding and have broader Access ");
        return null;
    }

}

class SubSix extends Super {

    public Super getClassName(Super s, String ol) {
        System.out.println(this.getClass().getSimpleName()+ " - I'm Perfect Overloading ");
        return null;
    }

}

class SubSeven extends Super {

    public Super getClassName(SubSeven s) {
        System.out.println(this.getClass().getSimpleName()+ " - I'm Perfect Overloading because Method signature (Argument) changed.");
        return null;
    }

}

public class Test{

    public static void main(String[] args) throws Exception {

        System.out.println("Overriding\n");

        Super s1 = new SubOne(); s1.getClassName(null);

        Super s2 = new SubTwo(); s2.getClassName(null);

        Super s3 = new SubThree(); s3.getClassName(null);

        Super s4 = new SubFour(); s4.getClassName(null);

        Super s5 = new SubFive(); s5.getClassName(null);

        System.out.println("Overloading\n");

        SubSix s6 = new SubSix(); s6.getClassName(null, null);

        s6 = new SubSix(); s6.getClassName(null);

        SubSeven s7 = new SubSeven(); s7.getClassName(s7);

        s7 = new SubSeven(); s7.getClassName(new Super());

    }
}
Maltzman answered 16/7, 2015 at 13:11 Comment(0)
G
0

Polymorphism relates to the ability of a language to have different object treated uniformly by using a single interfaces; as such it is related to overriding, so the interface (or the base class) is polymorphic, the implementor is the object which overrides (two faces of the same medal)

anyway, the difference between the two terms is better explained using other languages, such as c++: a polymorphic object in c++ behaves as the java counterpart if the base function is virtual, but if the method is not virtual the code jump is resolved statically, and the true type not checked at runtime so, polymorphism include the ability for an object to behave differently depending on the interface used to access it; let me make an example in pseudocode:

class animal {
    public void makeRumor(){
        print("thump");
    }
}
class dog extends animal {
    public void makeRumor(){
        print("woff");
    }
}

animal a = new dog();
dog b = new dog();

a.makeRumor() -> prints thump
b.makeRumor() -> prints woff

(supposing that makeRumor is NOT virtual)

java doesn't truly offer this level of polymorphism (called also object slicing).

animal a = new dog(); dog b = new dog();

a.makeRumor() -> prints thump
b.makeRumor() -> prints woff

on both case it will only print woff.. since a and b is refering to class dog

Guaranty answered 30/9, 2008 at 19:50 Comment(7)
some references: linuxtopia.org/online_books/programming_books/thinking_in_c++/…Guaranty
animal a = new dog(); a was constructed as a dog, and will print "woff". If you want it to print thump then you need to upcast it.((animal) a).makeRumor()Miseno
That's reference upcasting, but the object is still a dog. If you want it to be an animal, you must explicitly upcast the object.Miseno
Figured it out. Question was tagged Java. You answered C++. You may be correct in C++. I am definitely correct in Java.Miseno
should happen every time a copy constructor is involved here is a reference fredosaurus.com/notes-cpp/oop-condestructors/… case three matches; ignore the new operator which is there only to disambiguate creation.Guaranty
found a comprehensive (and better) explanation, for further reading: bytes.com/forum/post2982201-3.htmlGuaranty
sorry for the flames, I was making this example in c++ (as per the post) as java doesn't truly support polymorphism so it's difficult to differentiate between the concepts in the questionGuaranty

© 2022 - 2024 — McMap. All rights reserved.