0

I often read definitions for Polymorphism such as the following:

Polymorphism is the ability to have objects of different types understanding the same message

But the above definition also apply if we don't use Polymorphism, for example if we have an object of type Circle with a method draw(), and another object of type Rectangle with a method draw(), we can do:

circle1.draw();
rectangle1.draw();

So circle1 and rectangle1 understood the same message draw() without using Polymorphism!

Am I missing something?

user8437463
  • 357
  • 3
  • 6
  • Here the two `draw` calls are not really the _same_ message though, is it? I cannot say to an unknown object (which could either be `Circle` or `Rectangle`), `draw`, and expect them to understand, can I? – Sweeper May 06 '20 at 09:41
  • Hi, what you did here hides Polymorphism bebind it. The idea is that you have some farther Interface for both Circle and Rectangle and you can make some paint method in a ScreenRefresh class. That paint method shall draw all the "effects", animations, particles and shapes you have. It will ideally store everything in Drawable array and will do item.draw() in a loop. – Vitali Pom May 06 '20 at 09:45
  • The easy answer would be that the message is not `draw()`, but `Circle.draw()` and `Rectangle.draw()`. If there would be a common base class `Shape`, both `circle1` and `rectangle1` would understand the message `Shape.draw()` – the common message in this case. – tquadrat May 06 '20 at 10:17
  • @Sweeper *"Here the two draw calls are not really the same message though, is it?"* can we say that `circle1.draw()` does not send a `draw()` message to `circle1`, but rather it sends a `Circle.draw()` message? and if we do `Shape shape1 = new Circle(); shape1.draw();` (assuming `Shape` is a superclass of `Circle`), then `shape1` does not send a `draw()` message to the `Circle` object, but rather it sends a `Shape.draw()` message (and hence `Circle` objects now understand two messages: `Circle.draw()` and `Shape.draw()`, and these two messages have the same implementation/message handler)? – Tom Jun 20 '20 at 15:00
  • @Tom I meant that `Shape.draw` and `Circle.draw` are different messages under the condition `Shape` and `Circle` are unrelated types, which the OP seems to imply with the phrase "without polymorphism". I would say they are the same message if `Circle` inherits from `Shape`. – Sweeper Jun 21 '20 at 00:42
  • @Sweeper *"I would say they are the same message if Circle inherits from Shape"* are they actually the same message, or is it more accurate to say that if `Circle` inherits from `Shape`, then the `Circle` objects would now be able to understand the two messages `Circle.draw()` and `Shape.draw()` (which are two distinct messages and not the same message). – Tom Jun 21 '20 at 02:20
  • @Tom Well, I should probably point out that this is my own interpretation of the term "message". The JLS doesn't define it so in the context of Java, nothing is "more accurate" than anything... I simply find that thinking of it as `Circle` being able to understand one message, `draw`, is more useful when it inherits from `Shape`, because you can't normally call `Shape.draw` from outside. You' have to do `super.draw` _inside_ `Circle`. At least we both agree that when they are unrelated classes, the messages are distinct. :) – Sweeper Jun 21 '20 at 02:31
  • @tquadrat *"The easy answer would be"* why did you call it *"The easy answer"*, is it because your answer is not completely correct? – Tom Jun 23 '20 at 15:03
  • @Tom: My comment is correct, but not my English – it should not read "easy answer", but "simple answer". Both "simple" and "easy" can be translated to the same word in German, although the English words have a slightly different meaning. – tquadrat Jun 24 '20 at 07:07
  • @tquadrat So a message can be named in the format of `ClassName.MethodName()` (for example: `Circle.draw()` or `Rectangle.draw()` or `Shape.draw()`)? I am asking this because in this question: https://softwareengineering.stackexchange.com/questions/411697/what-does-common-interface-mean-in-oop, it is mentioned that a message can only be named something like `draw()` (i.e. without the class name before it). – Tom Jun 24 '20 at 21:52
  • @Tom: O ha, now you opened a big can of worms! "Syntactically", the name of the message is `draw`, without the class. But the class gives the semantical context, meaning that messages with the same name must not necessarily be the same in different contexts. That is more obvious for languages like Java where "message" is translated into "method invocation" than for languages that really use "messages". – tquadrat Jun 25 '20 at 10:03
  • @Tom: When designing a system, you should avoid any ambiguities regarding the names of messages, so the class as prefix is obsolete (and unwanted). And inside your system, `draw()` is always doing the same (in general, while the details could differ – that's Polymorphism). But someone else's design may have used `draw` for something else, in a way that is in no way aligned with your idea about that "message". If you now combine both systems, the distinction which `draw` you mean gets relevant. – tquadrat Jun 25 '20 at 10:10

4 Answers4

2

In your example, you have just two different classes, which methods "draw" are the same, but this in not polimorpfhism.

However, if you have an interface or abstract class like this:

public class pol {
    public static void main(String[] args) {
        Shape[] shapes = {new Circle(), new Rectangle()};
        for(Shape s: shapes) {
            s.draw();
        }
    }
}

interface Shape {
    void draw();
}

class Circle implements Shape{

    @Override
    public void draw() {
        System.out.println("Circle");
    }
}

class Rectangle implements Shape{

    @Override
    public void draw() {
        System.out.println("Rectangle");
    }
}

Then even if you access it as Shape, each individual method draw will be executed. So the output will be:

Circle
Rectangle
PastorPL
  • 968
  • 3
  • 17
  • 36
1

I want to share basic example:

interface Shape{
 void draw();
}

class Circle implements Shape{

    @Override
    void draw(){
    //Draw Circle here.
    }
}

class Rectangle implements Shape{

    @Override
    void draw(){
    //Draw Rectangle here.
    }
}

So in your example:

circle1.draw();
rectangle1.draw();

You can safely call draw method both circle and rectangle objects, because they are both shape actually. circle1 is both Circle and Shape, rectangle1 is both Rectangle and Shape. That is Polymorphism, object can be more than one type.

ibrahimdevs
  • 163
  • 7
0

The draw() methods you have mentioned are totally different and belong to different classes. Yes, in polymorphism the objects understand the method signatures but there are a little differences. For example imagine they have a method that sets diameter in both objects, without polymorphism you have to implement the method as much as objects you have! but for example define the area for every object in its own way because they are really different.

Majid Roustaei
  • 1,556
  • 1
  • 20
  • 39
0

Just in case you don't like technical answers...

A way to understand polymorphism would be "A way to make a code interact with various ways of doing the same thing, without knowing how it does it."

Lets say you have a program that prints data. The concept is really broad, so you first start with it reading from a txt file.
You called your class "TxtReader".
After implementing it, you quickly realize that txt is not a great way to save data....
So you decide to use a database.
Now you look at your code, and it is hard-coded to use TxtReader.read().

Changing code that was previously proven to be working is a terrible idea, as it can introduce new problems.
So -
You make an interface called "Reader", and give it one method "read()".

Now you go back to your code, and make TxtReader implement Reader. And you change the code to Reader.read(). Now you can make any amounts of Reader implementations, such as SqlReader, HtmlReader, PhpReader, etc, as long as it contains the method read().

Now all of those implementations will polymorph to a simple Reader when you want it to.

This allows you to write code without having to worry too much about what implementations there might be. So we like to use interfaces.

This is a small time saver for a single programmer, but a huge time AND money saver for any kind of project where there is more than one person doing the same job.