How to Organize Your Object-Oriented Code With Inheritance

It’s common to reuse code in object-oriented programming. Classes exist so that you can create objects without having to write the same variables and functions over and over again.

But what about classes themselves? Sometimes classes are very similar as well. For example, a tree has branches, roots, and a trunk. That applies to Elms, Oaks, and Ponderosa Pines.

If you were adding a tree to a game, you could create tree parts for dozens of trees. But it would be easier to create one tree class and have every other tree inherit its properties.

Why Is Inheritance Important?

There is a concept in object-oriented programming called “keep it DRY.” DRY stands for “Don’t Repeat Yourself.” If you find yourself copying and pasting a lot of code, you’re also introducing room for a lot of mistakes.

Let’s say you’re writing the code for a new Tamagotchi game. The first virtual pet will be a polar bear. So you create a class called PolarBear in JavaScript/TypeScript.

class PolarBear {
private _weight: number = 990;
constructor(weight: number = 0) {
this._weight = weight
}
makeNoise() {
console.log("made a roar");
}
eat() {
console.log("eats whatever it wants");
}
sleep() {
console.log("got a good night's sleep");
}
roam() {
console.log("wandered about aimlessly");
}
}

Then your boss tells you that upper management had a huge breakthrough. They realized it’s no longer the 90s and they can fit more than 5K of memory in the Tamagotchi. And now they want all the bears.

You roll up your sleeves and get back to work, creating copies of the bear class. Then your boss knocks on your door again. It turns out they want the game to be more educational. Now you have to add origin information to each pet.

You’re no longer duplicating code. Now you’re changing hundreds of lines of code for all eight species of bear. This is how mistakes happen, and bugs get introduced.

As you’re grinding away, your boss walks up yet again. Now upper management wants all the rodents in the game as well. Oh, and a giraffe.

You know that when you’re done, they’re going to want monkeys or something else as well. There must be a better way.

Instead of creating next generation Tamogatchi, you could always play with the existing ones.

Inheritance to the Rescue

In order to tame your virtual menagerie, you’re going to need to get organized. Inheritance helps you arrange your classes by adding parent and child relationships to them.

Black bears, grizzlies, and sloth bears are all bears. Bears, rodents, and monkeys are all animals. And that’s how we’ll structure our family tree.

This is what a portion of the code looks like:

class Animal {
private _weight: number;
private _origin: string;
constructor(weight: number = 0, origin: string = "") {
this._weight = weight;
this._origin = origin;
}
makeNoise(noise: string = "") {
console.log("made a noise that sounded like: " + noise);
}
eat(food: string = "") {
console.log("eats " + food);
}
sleep() {
console.log("got a good night's sleep");
}
roam() {
console.log("wandered about aimlessly");
}
}
class Bear extends Animal {
constructor(weight: number, origin: string) {
super(weight, origin);
}
makeNoise(noise: string = "roar") {
super.makeNoise(noise);
}
eat(food: string = "whatever it wants") {
super.eat(food);
}
}
class GrizzlyBear extends Bear {
constructor(weight: number = 600, origin: string = "North America") {
super(weight, origin);
}
}
class Panda extends Bear {
constructor(weight: number = 230, origin: string = "China") {
super(weight, origin);
}
makeNoise() {
super.makeNoise("squeek");
}
eat() {
super.eat("shoots and leaves");
}
}

You can play with the code in the TypeScript sandbox.

That was a big sample, but the code is simple enough, and all the classes are descended from the Animal class. You can see that Bear extends Animal. And GrizzlyBear and Panda extend the Bear class. The Bear class creates default sound and eat functions. The GrizzlyBear class uses those default functions, but the Panda does not.

In other words, the GrizzlyBear class does not override the Bear functions. Because GrizzlyBear extends Bear, it will use the functions defined by Bear automatically. But since Panda overrides the makeNoise and eat functions, it will use those instead.

Finding Relationships With the “is-a, has-a” Technique

To figure out if a class really should extend another class, you can ask yourself if there’s an “is-a” or “has-a” relationship between them.

  • A lemur “is-a” monkey.
  • A kangaroo “is-a” marsupial.
  • A rabbit’s foot is not a rabbit, though. A rabbit “has-a” foot.

This example is a little simplistic, but when dealing with real-world classes, it can be very helpful.

Hands-on Inheritance Practice and Understanding

Ready to apply what you’ve learned?

  • Visit the sandbox and fill in the rest of the animal classes from the example above.
  • Add a Monkey class.
  • Add a ProboscisMonkey class that extends your monkey class.

Inheritance is more than just well-organized code. It’s a core part of object-oriented programming. Inheritance helps streamline communication between objects. And it allows for more advanced object-oriented design, like with polymorphism. You can learn more about inheritance from the TypeScript documentation.

Source: makeuseof.com

Related posts

Why I Regret Buying an Apple Magic Keyboard for My Mac

How to Change the Font of a Paragraph Style in Google Docs

Windows Cloud Download vs. Local Reinstall: How Do They Differ?