Lesson 22 - "Is-A" Inheritance Containment

Tutorial Series: Introduction to Unity with C# Series

Previous Article  |  Next Article


In that last video, I mentioned the basics of this 'Has-a' containment structure, where one class has within it an instance of another class, such as our Wizard class having a field of type Weapon. There is another way to incorporate code from another class, an outside class, and that is with inheritance, but it does so in a very different way than we have seen so far. We've shied away from talking about inheritance, I think we're ready to talk about it now. Inheritance is very simple at the heart of it, and is a way of associating classes in much the same way we think of class hierarchies in the real world. Remember we were originally talking about a class for human, a human class or a person class. What broader class can you think of that humans, as a class, inherit characteristics from? That you can say they inherit characteristics from. That is to say all humans are also a subclass of this other class. How about mammals? All humans are mammals, which is a broader class that can apply to humans as well as other animal classes.

Let's write out how this would look like in code, when inheriting having a Human class inheriting from a broader Mammal class. The first thing we're going to want to do is, as usual, create a new script for this. Let's create our Pure C# classes first. Let's call this AnimalClasses. As before, we don't need to inherit, nor do we want to inherit, from MonoBehaviour. The first thing we'll do is we'll create our Human class, as we did before, at least very similar. Let's just rename that to Human. For the Human class, let's just give it a somewhat unique feel that would be unique to the Human class. Let's say "public bool Bipedal." Walks on two legs. We'll set that to true. Not that we have to, but just to illustrate our point. In an entirely different class, which we can write anywhere but we'll write it above our Human class, let's make our Mammal class, and within it, give it some field that is essential to that particular class, some essential field that belongs to all Mammals. How about let's say this. public bool LaysEggs We'll set it to false, again, just for illustrative purposes. Now, let's do this. Let's simply inherit from that Mammal class, so Humans inherit the characteristics, the fields and such from the Mammal class, simply by referencing the Mammal class with the colon here. When that comes after the class name, this means "inherits from," that's how you can read it, and then you simply reference the outside class, in this case the Mammal class.

Then to see the result of this, as usual, we'll make a separate class so we can create our instance and so forth. We'll call this script, AnimalFactory. It derives from MonoBehavioru, as usual, and we'll preserve the Start() method as usual as well, so we can use it to output to Unity. In the Start() method, write this. We'll create first our instance of a Human, call it person = new Human() We've got our instance now. Now to our Debug.Log(), watch this. Let's output the fields available to us in the person variable object instance. person, and with IntelliSense, after hitting the dot accessor, I get not only Bipedal, which is directly a field that is made available within our Human class, but we also get the LaysEggs field. Now let's go to Unity. Attach that factory script to our test game object, as usual, and we'll output it, just so you can see. False. In case it isn't obvious, that's the value that we set for lays eggs, going back to our animal classes. That's why that's outputting. As you see here, by inheriting from the class "Mammal," we're quietly importing all of the fields and methods defined in the Mammal class into the Human class. You can see just with IntelliSense alone how that's the case. I just showed you that when we were referencing the LaysEggs field.

Now, this containment structure has its own uses. As you recall, our game scripts that we've been writing so far have all been inheriting from MonoBehaviour, and that's why I'm mainly showing you inheritance right now. In contrast to the Has-a containment structure that we saw in the previous video, this inheritance structure would be called an "Is-a" structure. In other words, a Human is a Mammal, where as before we had a Wizard has a Weapon, with that containment structure. Just like the code reuse benefit we got from the Has-a containment structure, we were able to reuse that object from the Weapon class blueprint in both the Wizard and Knight class. We just reuse that code there. We're able to reuse it in those different classes. Just like that reuse benefit with that Has-a containment structure, where multiple classes can incorporate other classes' code by having it as a field, for example, you can get code reuse with inheritance by having other classes inherit from it as well. Let's illustrate that with this example. Let's make another class that can inherit from the Mammal class. How about class Dog, inherits from Mammal. It can have its own fields along with now inheriting the LaysEggs field, just like the Human class had its own class for Bipedal. It's actually important to realize right now that when you see this, it's not an empty class. It would be an empty class if we didn't inherit from Mammal, but make no mistake, there's this code that is being inherited, and you'll see this often in Unity where classes might look relatively small, but they're actually much larger simply by virtue of them inheriting or from being a sub-class of outside classes. We'll just give the Dog class its own Bipedal value, which we know is false. Four-legged, right?

In the end, the way we gain access to that code from the outside class, from inheritance is a bit different than if we did it through containment. As with inheritance, we're directly importing the inherited code. In an Is-a inheritance relationship between classes, it'll make most sense to use that when several classes have the same basic code definition with maybe minor differences, because inheritance actually allows us to be more flexible with those differences than with simple Has-a containment would allow. It lets us override inherited properties or fields and methods, for example, but I don't really want to get into that just yet. Just do know that and keep that in mind, that that's where it's useful. It's up to you ultimately in the end, as the programmer with all these tools being given to you, to choose an inheritance versus containment structure where and when you see fit. There isn't really anything written in stone. The Is-a and Has-a idea that I've been presenting to you is just a guideline. In some cases, it may make more sense to inherit code from another class than have an instance field of that outside class, or vice versa.

We won't really go too deep into showing you this where and when you make this choice. A lot of it becomes intuitive or becomes a matter of choice. Different programmers will have very different ways of representing or solving problems in code. I just wanted to show you the basic principles of inheritance right now and contrast it with this Has-a containment structure, for the purposes of understanding Unity's code base in general, which itself makes extensive use of both inheritance and object containment. That's why we're looking at it right now.

Related Articles in this Tutorial:

Lesson 1 - Who This Course is For

Lesson 2 - What to Expect from this Course

Lesson 3 - Installation and Getting Started

Lesson 4 - Starting the First Project

Lesson 5 - Prototype Workflow

Lesson 6 - Basic Code Review

Lesson 7 - Game Loop Primer

Lesson 8 - Prototyping Continued

Lesson 9 - C# Fundamentals and Hello World

Lesson 10 - Variables and Operations

Lesson 11 - Variables and Operations Continued

Lesson 12 - Floats, Bools and Casting

Lesson 13 - If Statement Conditionals

Lesson 14 - If Statements Continued

Lesson 15 - Complex Evaluations and States

Lesson 16 - Code Syntax vs. Style

Lesson 17 - Variable Scope

Lesson 18 - Object-Oriented Programming Intro

Lesson 19 - OOP, Access Modifiers, Instantiation

Lesson 20 - Object Containment and Method Returns

Lesson 21 - "Has-A" Object Containment

Lesson 22 - "Is-A" Inheritance Containment

Lesson 23 - Static Fields and Methods

Lesson 24 - Method Inputs and Returns

Lesson 25 - Reference vs. Value Types

Lesson 26 - Introduction to Polymorphism

Lesson 27 - Navigating the Unity API

Lesson 28 - Applying What You've Learned and Refactoring

Lesson 29 - Constructors, Local Variables in the Update Method

Lesson 30 - Collecting Collectibles, Items and Powerups

Lesson 31 - Spawning and Managing Prefab Powerups

Lesson 32 - Implementing Powerup State Logic

Lesson 33 - Displaying Text, OnGUI, Method Overloading

Lesson 34 - Referencing Instantiated GameObjects, Parenting

Lesson 35 - Understanding the Lerp Method

Lesson 36 - Creating Pseudo Animations in Code

Lesson 37 - Understanding Generic Classes and Methods

Lesson 38 - Animations Using SpriteSheets and Animator

Lesson 39 - Working with Arrays and Loops

Lesson 40 - Debugging Unity Projects with Visual Studio

Lesson 41 - Camera Movement and LateUpdate

Lesson 42 - Playing Audio Clips

Lesson 43 - Routing Audio, Mixers and Effects

Lesson 44 - Adding Scoring Mechanics and Enhancements

Lesson 45 - Scene Loading and Game Over Manager

Lesson 46 - Understanding Properties

Lesson 47 - Controller Mapping and Input Manager

Lesson 48 - Understanding Enums

Lesson 49 - Dealing with Null References

Lesson 50 - Handling Variable Framerates with time.DeltaTime

Lesson 51 - Preparing the Project for Final Build

Lesson 52 - Final Build and Project Settings

Lesson 53 - Introduction to the Unity Physics Engine

Lesson 54 - Understanding FixedUpdate vs. Update

Lesson 55 - Movement Using Physics

Lesson 56 - Attack Script and Collision Events with OnCollisionEnter2D

Lesson 57 - Projectiles and Stomping Attack

Lesson 58 - Parallax Background and Scrolling Camera

Lesson 59 - Infinitely Tiling Background Sprites

Lesson 60 - OOP Enemy Classes

Lesson 61 - OOP Enemy Classes Continued

Lesson 62 - Trigger Colliders and Causing Damage

Lesson 63 - Multi-Dimensional Arrays and Procedural Platforms

Lesson 64 - Finishing Touches

Lesson 65 - Series Wrap


Please login or register to add a comment