0

I want to make diagrams that explain how Inheritance and Polymorphism work conceptually.

Assume that we have a Cat class that inherits from the Animal class. The way that I can think of a Cat object is that it is an object that contains a copy of the members of the Cat class and also it have an Animal object inside of it.

Note: technically, I think that all Cat objects share the same copy of the methods of the Cat class, however, it is clearer to conceptually think of every Cat object as if it contains its own copy of the methods of the Cat class.

Now when we do:

Cat cat1 = new Cat();

Then cat1 will point to the Cat object, this is how the diagram would look like:

enter image description here

The operations that are allowed on the cat1 variable are the following:

  • cat1.x (will access the x variable inside the Cat object).

  • cat1.move() (will call the move() method inside the Cat object).

  • cat1.jump() (will call the jump() method inside the Animal object).

And when we do:

Animal animal1 = cat1;

Then animal1 will point to the Animal object that is inside the Cat object, this is how the diagram would look like:

enter image description here

Note: the arrow pointing at the Animal object doesn't mean that animal1 actually point to a different location in memory than cat1, the truth is that animal1 and cat1 point to the same location in memory, the arrow pointing at the Animal object is just to indicate that animal1 can only access the members inside the Animal object (unless we have an overridden method).

The operations that are allowed on the animal1 variable are the following:

  • animal1.x (will access the x variable inside the Animal object).

  • animal1.move() (now if the move() method is not overridden in the Cat class, then animal1.move() should call the move() method inside the Animal object, however, since the move() method is overridden in the Cat class, then animal1.move() would call the move() method inside the Cat object).

  • animal1.jump() (will call the jump() method inside the Animal object).

Is my understanding correct?

3

I think to do this right you need to detach the method names from the object blocks. The whole point of polymorphism is the separation of the interface from the implementation. It does not help to see the method names within a particular object block, that is only confusing. The method names should be on the outside, at the outer edge of the outer block. Then some lines can route them to the inners of a particular object where the attached implementation is, without repeating the member names. The point is to show where the pipes end up.

Another thing that is (utterly) wrong in the drawings shown is that when you cast the object to Animal, the arrow goes to Animal. This is not the case, the arrow should still go to Cat! You will be talking to a Cat no matter what you cast it to. Once you understand this you really understand polymorphism and it will get a lot easier, this is what you want to make clear.

[edit]

The pictures are portraying the objects (ancestor and descendant) as separate things which gives the wrong idea. The point is they are the same, which is not conveyed by the image. Descendant does not encapsulate/contain ancestor, descendant is an extension/modification of ancestor. Once the cat object is instantiated there is no animal object.

The animal class is used as a blueprint to construct part of the cat object but the result will be a cat. Think of the real cat, does it have an animal inside of it? No. So the "animal object" box within the cat object box is inappropriate, it is all cat.

5
  • 2
    agree. What diagraming paradigm is that anyway? Booch diagrams? I haven't used those for 20+ years. All the OPs representational concerns are handled in Unified Modeling Language (UML). Sequence diagrams in particular are great for illustrating object instantiation call order. – radarbob Jul 20 '20 at 18:07
  • 1
    An additional misleading feature of this idea of showing a cat wrapping an animal is that it makes you think of aggregation instead of inheritance. Subclasses should not be depicted as containing the supperclass. When the time of depicting actual aggregation, how will he depict it? – Tulains Córdova Jul 20 '20 at 18:27
  • @radarbob That’s not booch. Boochbis recognizable among 1000 with its cloud-formed classes. That’s op freestyle for teaching purpose. – Christophe Jul 20 '20 at 19:36
  • @Tulains Córdova I putted the superclass object inside the subclass object to indicate that the superclass members are now part of the subclass object (for example: when we do cat1.jump(), we can assume that the jump() method is part of the Cat object). However, if I would have created separate diagrams for both the Cat object and the Animal object, then it would not be obvious that the Animal members are part of the Cat object... – Tom Jul 21 '20 at 5:45
  • @Tulains Córdova ...As for how can I depict aggregation, I can do that by putting a variable name before the member object diagram (like I did with the x variables), while the Animal superclass object diagram doesn't have a variable name before it, so this way it would be obvious to distinguish between the superclass object diagram and the member object diagram (by "member object diagram" I mean the object diagram of the object that is a member of another object). – Tom Jul 21 '20 at 5:45
2

In the second case, with polymorphism, animal1.move() will still invoke move() of the Cat. In this regard, the diagram is misleading.

If you want to get this right and unambiguous in a diagram, you'd have to draw some kind of redirection of the call to the right method whatever the type that is used:

  • a vtable-like presentation in your embedded box diagram
  • or simply lollipop connectors, to show that it's like a plug with some special wiring behind the wall.

Elaborating on what you did, I could fo example imagine something like this:

enter image description here

The second alternative that I mentioned, uses the lollipop connectors that you typically find in an UML component and the view of the internal subobjects like you'd fin in an UML composite structure:

enter image description here

I hesitated to show it, because it looks like UML, but it's not valid UML. The lollipops for example are used to show public members instead of full interfaces, and the ports are misused to route the call to the right implementation instead of component elements. In addition your typed object handles do not consume the interface but provide. On the other side, it could have advantages to familiarize your students intuitively with these modelling principles: it's a good opportunity to make seem natural what otherwise looks rather abstract.

9
  • Isn't that what Tom said? (In the second bullet-point, he gives the "without-override" and "with-override" scenarios: "however, since the move() method is overridden in the Cat class, then animal1.move() would call the move() method inside the Cat object") Agree the diagram is rather misleading. – SusanW Jul 20 '20 at 15:38
  • @SusanW I must say that reading it I'm still not sure. But in any case, the diagram is misleading. I'll edit to clarify. – Christophe Jul 20 '20 at 15:41
  • @Christophe "the diagram is misleading" Are you saying this because animal1 is pointing to the Animal object while animal1.move() is not calling the move() method inside the Animal object? – Tom Jul 20 '20 at 15:51
  • @Tom indeed. >The diagram doesn't show that another move() is called than the one that is in the box. You must show that ,even if you point at animal it's the other move that is executed. You can do this by showing some wiring. By the way, the second x is misleading: it should be like the jump: you only have one, and it's the one in animal – Christophe Jul 20 '20 at 15:55
  • 1
    @Tom and yes, if the x of cat is inherited from animal, there's only one x in the Cat. I've tried to show this in an alternate diagram that show who provides what (so x is in animal and jump only in cat) but cat provides another method + its own implementation of move(). THe grey parts are accessible from outside, but the wiring makes sure that whatever object is used, the right method is called (polymorphism). – Christophe Jul 20 '20 at 16:26

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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