UML Inheritance

With the ambition to make it easy for people to benefit from object-oriented approaches using MDriven and MDriven Designer, I will in this post give a quick introduction to UML inheritance.

UML inheritance is different from “I get you stuff when you die”. It is also different from “Oh look that kid really looks like her Mother”.

UML inheritance is this: “A child class has all attributes and associations that a parent class has, and the child also has attributes and/or associations of its own that the parent does not have”. In other words UML inheritance is “specialization” and “generalization”; a child class is a “specialized” version of the parent, and a parent is a more “generalized” definition of the child class.

UML inheritance is the same as OO-inheritance (Object oriented inheritance).

UML inheritance will allow you to inherit the properties of multiple parents – but very few OO-languages allow for, so called, multiple inheritance (c++ does, c# & VB.NET does not, and since eco focus on the latter languages eco does not support it either), so I will not mention multiple inheritances again in this post. This means that a class can only have one parent class (or no parent class of course, but never many parents).

An example

Fruit. Fruit is pretty generic class. If we think of specializations of fruit we will find apple, orange, pear, banana, pineapple etc.

FRUIT MODELS.png

The lines ending with the big arrow is called a Generalization-association, meaning that if you follow it you get something more generalized of the class that you leave. If you follow it in the other direction you get the opposite of generalization, namely specialization. You will notice in MDriven that when you add a generalization associations, the class’s superclass is updated in the object inspector.

Properties fruits.png

Superclass is more correct UML term than “Parent class”. And instead of “Child class” the correct UML terminology is Subclass. So I will use Super- and Subclass from now and on.

Why is inheritance so useful?

The obvious benefit of inheritance is the ability to introduce common properties that all fruit has in one place. If there are properties that all fruit has they will go into the Fruit class rather than defining them over and over in the subclasses.

Model fruits + subclasses.png

The true power of inheritance is that it resembles how people reason and think. As humans we always generalize. Our language and communication depends on it. This fact is the reason for some bad things in society – prejudice where we jump to conclusions based on earlier experience or hearsay, and some good things – that we instantly know how to use a door knob even if we have never seen that particular type of door knob before.

With the model, we have now we can see the benefit that strong types give. Our code will now look like this:

1: Country malaysia=new Country(this.ServiceProvider());
2:
3: Apple apple = new Apple(this.ServiceProvider());
4: Orange orange = new Orange(this.ServiceProvider());
5:
6: apple.GrowsInTheseCountries.Add(malaysia);
7: orange.GrowsInTheseCountries.Add(malaysia);
8:
9: foreach (Fruit fruit in malaysia.ExportsTheseFruits)
10: {
11:     if (fruit is Apple)
12:     {
13:       // Do apple specific operations
14:     }
15:     else if (fruit is Orange)
16:     {
17:         // Do orange specific operations
18:     }
19: }

Polymorphism

Polymorphism is a fancy word for an important concept: poly==many, morph==shape => many shapes. In our example we use polymorphism in the association from country to fruit; namely a resulting list that can contain different subclasses of fruit – apples and oranges etc.

Polymorphism allows us to operate on stuff we do not really know that much about. 

Check this out:

Fruit model 2.png

I add a method on fruit that I make virtual:

Properties 2.png

I can implement this to return a default value on Fruit and override it on the subclasses that should return a different value:

Overrided subclasses fruits.png

1: public partial class Fruit {
2:     public virtual bool HasSeedsYouNoticeWhenYouEat()
3:     {
4:         return true;
5:     }
6: }
1: public partial class Banana {
2:     public override bool HasSeedsYouNoticeWhenYouEat()
3:     {
4:         return false;
5:     }
6: }

So having this I can write code that goes over a list of Fruit and ask if the fruit HasSeedsThatYouNoticeWhenYouEat like this:

1: List<Fruit> crapfruit = new List<Fruit>();
2: List<Fruit> okfruit = new List<Fruit>();
3: foreach (Fruit fruit in malaysia.ExportsTheseFruits)
4: {
5:     if (fruit.HasSeedsYouNoticeWhenYouEat())
6:         crapfruit.Add(fruit);
7:     else
8:         okfruit.Add(fruit);
9: }

If you are still with me I also want to mention the concept of “Abstract”. When we have a model like the one above you should really think of the Fruit class as being abstract – meaning that having an instance of a fruit (a real fruit) that is of type Fruit should not be legal. A fruit-instance must be one of the subclasses; it can be an Apple, Pear, Orange, Banana or PineApple (in our model) but never just “Fruit”.

In Object orientation terms Abstract means that the compiler will treat any attempt to create an instance as an error. It is an error because the developer that defined the class never intended it for direct use, it was designed as an abstraction or generalization of a set of subclasses.

My recommendation is to always treat classes that have subclasses (aka superclasses) as being abstract. In the Fruit sample above this might be obvious, but remember this when you classify your domain where it might not be so obvious.

This page was edited 24 days ago on 04/02/2024. What links here