1. Pegasus
Let's take a deeper look at the third principle of OOP: inheritance. This is a very interesting topic that you will use often. To the uninitiated, programming is indistinguishable from magic. So let's start with an interesting analogy...;
Let's say you are a wizard who wants to create a flying horse. On the one hand, you could try conjuring a pegasus. But because pegasi do not exist in nature, this will be very difficult. You will have to do a lot yourself. It's much easier to take a horse and conjure its wings.
In programming, this process is called "inheritance". Suppose you need to write a very complex class. It takes a long time to write code from scratch and then test everything for a long time to look for errors. Why go the hard way? It's better to look to see whether such a class already exists.
Suppose you find a class whose methods implement 80% of the functionality you need. What do you do with it next? You could just copy its code into your class. But this solution has several drawbacks:
- The class you find may already be compiled into bytecode, and you may not have access to its source code.
- The source code of the class is available, but you work for a company that could be sued for a couple of billion for using even 6 lines of someone else's code. And then your employer will sue you.
- Unnecessary duplication of a large amount of code. Additionally, if the author of an external class finds a bug in it and fixes it, you will still have the bug.
There is a more elegant solution, and it doesn't require getting legal access to the original class's code. In Java, you can simply declare that class as the parent of your class. That will be equivalent to adding the code for that class to your own code. Your class will see all the data and all the methods of the parent class. For example, you can do this: we inherit "horse" and then add "wings" to get a "pegasus"
2. Common base class
Inheritance can be used for other purposes as well. Let's say you have ten classes that are very similar. They have the same data and methods. You can create a special base class, move the data (and associated methods) into this base class, and declare those ten classes to be descendants. In other words, in each class indicate that its parent class is this base class.
Just as the advantages of abstraction are revealed only along side encapsulation, so too are the advantages of inheritance much enhanced when using polymorphism. But you will learn about that a little later. Today we will look at several examples of using inheritance.
Chess pieces
Suppose we are writing a program that plays chess with a human user. Accordingly, we need classes to represent the pieces. What classes would they be?
If you've ever played chess, the obvious answer is King, Queen, Bishop, Knight, Rook and Pawn.
But the classes themselves would still need to store information about each piece. For example, the x and y coordinates, and the value of the piece. After all, some pieces are more valuable than others.
In addition, the pieces move differently, which means that the classes will implement different behavior. Here's how you could define them as classes:
|
|
|
|
|
|
This is a very primitive description of chess pieces.
Common base class
And here's how you could use inheritance to reduce the amount of code. We can bring the common methods and data into a common class. We'll call it ChessItem
. There's no point in creating objects of the ChessItem class
, since the class doesn't correspond to any chess piece. That said, the class will prove very useful:
|
|
|
|
||
|
|
|
This is a great way to simplify the code for similar objects. The benefits are particularly noticeable when there are thousands of different objects and hundreds of classes in the project. So properly selected parent (base) classes let you not only greatly simplify the logic, but also reduce the code tenfold.
3. Class inheritance — extends
So what does it take to inherit a class? For one class to inherit another, you need to write the extends
keyword after the child class declaration and then write the name of the parent class. It usually looks something like this:
class Descendant extends Parent
This is what you need to write when declaring the Descendant class. By the way, a class can inherit only one class.
In the picture, we see that a cow inherited a pig, which inherited a chicken, which inherited an egg. Only one parent! Such inheritance is not always logical. But when all you have is a pig and you really need a cow, programmers often cannot resist the urge to make a cow out of a pig.
Java does not have multiple inheritance: a class cannot inherit two classes. Each class can have only one parent class. If no parent class is specified, the parent class is Object
.
That said, Java does have multiple inheritance of interfaces. This mitigates the problem slightly. We'll talk about interfaces a little later, but for now let's continue to explore inheritance.
GO TO FULL VERSION