Lessons.OOP.EC

Programming OOP Lesson:
Class Inheritance

The Base Class

A base class is a class that is used to generally describe something while a subclass describes something more specifically. For example, a base class could be a blueprint for any house while a subclass of that blueprint may be a ranch home. For the Zoo Simulator project we will create a general Animal base class that will have a number of subclasses that represent different animal families and animals.

  • 1. Create a new project called "Zoo"
  • 2. Create a new class called "Animal"
  • 3. Download this code to use for the class

Let's go over what the code in this class does.

Private picture As Image
Private foodType As Food
Private hunger As Integer = 0
Private boundary As Rectangle
Private location As Rectangle
Private speed As Integer
.
.
.
Enum Food
   None
   Grass
   Meat
End Enum

The variables in the base class are all declared private so they are not accessible outside the class unless we want them to be. Most of the variables should be self-explanatory, but note that boundary and location are declared as Rectangles. A Rectangle is made up of an x, y pair that specifies the upper-left corner of the object and a width and height.

Public Sub New(ByVal picture As Image, ByVal foodType As Food, ByVal boundary As Rectangle, ByVal location As Rectangle, ByVal speed As Integer)
   Me.picture = picture
   Me.foodType = foodType
   Me.boundary = boundary
   Me.location = location
   Me.speed = speed
End Sub

The constructor sets the initial value of five variables based on the information it was given. When we create a new animal we need to send it those five things somehow, which we will do in this lesson.

Public ReadOnly Property getPicture() As Image
   Get
      Return picture
   End Get
End Property
.
.
.
Public Property getHunger() As Integer
   Get
      Return hunger
   End Get
   Set(ByVal value As Integer)
      hunger = value
   End Set
End Property

The properties allow access to the variables from outside the base class. The are not all listed above since most of them are simply the read-only properties that we learned about for the Hangman project. The property for hunger, however, is not a read-only property, which means it has something known as a set accessor. A set accessor determines what happens when something outside the class tries to assign a value to the variable. We need this for hunger because we may need to change the hunger of some animals in the subclasses. None of the other variables require a set accessor.

Public Overridable Function Eat(ByVal food As Integer) As Integer

End Function

Public Overridable Sub Roam()
   Dim rndNum As Random = New Random
   Dim move As Integer = rndNum.Next(0, 5)

   If move = 1 And CollisionTop() Then
      Dim newY As Integer = location.Y - speed
      location = New Rectangle(New Point(location.X, newY), location.Size)
   ElseIf move = 2 And CollisionRight() Then
      Dim newX As Integer = location.X + speed
      location = New Rectangle(New Point(newX, location.Y), location.Size)
   ElseIf move = 3 And CollisionBottom() Then
      Dim newY As Integer = location.Y + speed
      location = New Rectangle(New Point(location.X, newY), location.Size)
   ElseIf move = 4 And CollisionLeft() Then
      Dim newX As Integer = location.X - speed
      location = New Rectangle(New Point(newX, location.Y), location.Size)
   End If
End Sub

The functions above are both declared as overridable. We will talk about what this means later. The Eat function is used to cause the animals to eat, but it has not been written yet. The Roam function is used to move the animal. A random number is created between 0 and 5. If the number is 0 the animal does not move. If it is between 1 and 4 the animal will move in one of four directions. A new x location or y location is created depending on the direction of movement. A new rectangle is then created for the location. Finally, the if statements check for the direction of movement and they also call one of four collision detection functions, which are explained below.

Public Function CollisionTop() As Boolean
    If location.Top - speed <= boundary.Top Then
        Return False
    Else
        Return True
    End If
End Function

Public Function CollisionBottom() As Boolean
    If location.Bottom + speed >= boundary.Bottom Then
        Return False
    Else
        Return True
    End If
End Function

Public Function CollisionLeft() As Boolean
    If location.Left - speed <= boundary.Left Then
        Return False
    Else
        Return True
    End If
End Function

Public Function CollisionRight() As Boolean
    If location.Right + speed >= boundary.Right Then
        Return False
    Else
        Return True
    End If
End Function

Collision Detection

Although a Visual BASIC form isn't set up exactly the same, it is similar to Region IV in the coordinate plane. The only difference is there are no negative numbers on the Visual BASIC form.

Coordinate Plane

Form Coordinates

In the picture above the upper-left hand corner, which is the origin of the form is located at (0, 0). If you move a form component down the form the Y value will increase and if you move it to the right the X value will increase. Moving a component off the form to the left or top will make the numbers negative. Try playing around with this until you have an understanding of how the coordinate system works on a form.

The way the collision detection works, then, is that it adds or subtracts the animal's speed to the current location to see where the animal will be located in the future. If that point is past the boundary of the animal then the function returns false, indicating the animal should not be allowed to move.

Class Inheritance

When a class has more specific cases of something in a base class it is known as a subclass of that base class. A subclass may have more specific functions or variables of the base class, but it is said inherit from the base class.

A class hierarchy shows the order of base classes and subclass starting with the most general (the base class) to the most specific. Below are some examples of class hierarchy.

Food Class Hierarchy

A recipe that calls for cheddar cheese can be made with any type of cheddar including Wisconsin Cheddar, but if the recipe calls specifically for Wisconsin Cheddar you would not be able to use Vermont Cheddar.

Animal Class Hierarchy

A lower class in the hierarchy inherits all, or most, of the attributes of everything above it. For example, an animal eats and roams, a bird has wings and flys, and a songbird sings. Since a Mockingbird inherits from Songbird it must eat, roam, have wings, fly, and sing.

Now let's see how we set up a class that inherits from another class. We will set up a Feline class as well as a Tiger class.

Subclasses

When you create a subclass you need to specify that it inherits from another class. We will do that with the Feline class.

  • 4. Create a new class called "Feline"
  • 5. Add the code below to the new class

Public Class Feline
    Inherits Animal

    Public Sub New(ByVal picture As Image, ByVal boundary As Rectangle, ByVal location As Rectangle)
        MyBase.New(picture, Animal.Food.Meat, boundary, location, 5)
    End Sub

    Public Overrides Function Eat(ByVal food As Integer) As Integer

    End Function
End Class

 

The Inherits Animal section is what indicates that this is a subclass of Animal. You always want to inherit the class directly above the current class in the hierarchy. The constructor only takes three parameters since we set the FoodType and Speed when we call the base class. Typing MyBase.New calls the constructor of the base class.

Also note that the Eat function has the word overrides in it. This means that this Eat function will run instead of the Eat function in the Animal class. In the case of multiple method definitions like this the most specific method will run. You will have to figure out how to write the Eat function on your own, but remember that can use MyBase to access anything in the base class.

Finally, let's create the Tiger class.

  • 6. Create a new class called "Tiger"
  • 7. Add the code below to the new class

Public Class Tiger
    Inherits Feline

    Public Sub New(ByVal picture As Image, ByVal boundary As Rectangle, ByVal location As Rectangle)
        MyBase.New(picture, boundary, location)
    End Sub
End Class

 

The code should make sense in this class. There are no functions in this class because it is up to you to decide if the tiger should act differently from other felines. For example, it may eat faster than other felines so it may override the Eat function. It may also move at a different pace than other animals so it could override the Roam function as well.

Class Instances

We are now going to create some code that will add the tiger to a pen. First, you will need to add a few PictureBoxes to your Form.

The Form

  • 8. Add three PictureBoxes to your form
  • 9. Put one PictureBox on top of another as shown above
  • 10. Rename the large PictureBox "picPen1"
  • 11. Rename the small PictureBox "picAnimal1"
  • 12. Rename the other PictureBox "picTiger"
  • 13. Add an image or background color to picPen1
  • 14. Add an image of a tiger to your Project Resources
  • 15. Add the code below to the top of your Form

Public Class frmZoo
    Private selectedPen As Integer
    Private animals(4) As Animal
    Private pens(4) As PictureBox
    Private penPic(4) As PictureBox

Public Sub New()
    ' This call is required by the Windows Form Designer.
    InitializeComponent()

    ' Add any initialization after the InitializeComponent() call.
    pens(0) = picPen1

    penPic(0) = picAnimal1
End Sub

The animals array will hold any instances of the animal class that we create. The pens array holds the name of all the pens, and the penPic array holds the name of the animals within the pens. Finally, the user will need to click on a pen before they click on the animal they want to put in that pen. We need the selectedPen variable to keep track of which pen was clicked. The constructor only fills index 0 of pens and penPic, but for the project you will populate the rest of the indices.

  • 16. Double-click the pen and add the following code:

Private Sub picPen1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles picPen1.Click
    selectedPen = 1
End Sub

Now we need to program the tiger picture to create a new instance of the Tiger Class.

  • 17. Double-click picTiger and add the following code:

Private Sub picTiger_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles picTiger.Click
    animals(selectedPen - 1) = New Tiger(My.Resources.tigerSprite, New Rectangle(pens(selectedPen - 1).Location, pens(selectedPen - 1).Size), New Rectangle(pens(selectedPen - 1).Location, penPic(selectedPen - 1).Size))
End Sub

 

The code above creates a new instance of the Tiger Class and stores in in animals(selectedPen - 1). In this case it will be stored in animals(0) since we only have pen 1 created. The first parameter sent to the Tiger Class is the picture of the tiger. Yours might be slightly different depending on what you named the picture you added. The other two parameters are the same since the boundary and location start the same since the picture of the animal starts in the upper-left corner of the pen.

Finally, we will create a method to add the animal to the pen.

  • 18. Type "newAnimal()" at the bottom of the picTiger code above
  • 19. Add the following method code somewhere in your Form Class:

Private Sub newAnimal()
    penPic(selectedPen - 1).Image = animals(selectedPen - 1).getPicture
    penPic(selectedPen - 1).Visible = True
End Sub

The first line of the method above gets the correct picture from the Animal Class and adds it to the correct PictureBox. It then makes the PictureBox visible since we may make it invisible at some time in our program. You should be able to make the tiger appear now. To finish the project, create a class for a house cat and create a PictureBox that will allow you to add one to the pen.

  • 20. Create a Cat Class and program a way to add a cat to the pen