More on Classes

With the basics of classes covered, we dive deeper into the ideas of classes and OOP and begin to look at subclasses, inheritance and polymorphism.

First let’s take a look at subcalsses. As someone from a maths background this idea followed very naturally from the idea of subsets, and is essentially a way of grouping objects in a hierarchical structure. A car is a type of vehicle so one could say a car is a subclass of vehicle, equally a dachshund is a subclass of dog which itself is a subclass of pet. We say that the pet class is the superclass (just like superset in set theory) of the class dog. As with set theory we have implications about the objects in each class for example

  • All dachshunds are dogs
  • All dachshunds are pets
  • All dogs are pets
  • Not all pets are dachshunds
  • Not all pets are dogs

With this idea of hierarchical structure comes the notion of inheritance of certain features an object may have; for example all pets have names, so since a dog is a pet we would expect it to have a name.

So now we have a feel for the intuitive notion of subclasses and inheritance let’s see how we’d code it up. Sticking with pets, dogs and dachshunds we first make our pet class (like last time) and define the __init__ method that takes a name and an age. We’ll also add a method called Birthday that wishes the pet happy birthday and increments its age.

class Pet():
    
    def __init__(self,name,age):
        self.name = name
        self.age = age
        
    def birthday(self):
        print('Happy Birthday ' + self.name + '!')
        self.age = self.age + 1

To define a subclass no new syntax is needed, we simply pass the class we want as a superclass as an argument when defining the class. So let’s make the dog class and define the __init__ method as well as a method called talk

class Dog(Pet):
    
    def __init__(self,name,age,good_dog):
        super().__init__(name,age)
        self.good_dog = good_dog
    
    def talk(self):
        print('Woof')

Note on line 4 the syntax super().__init__(name,age). Here we are calling the initialise methd of the superclass Pet.

We now have all the tools to observe the features of subclasses and inheritance. Creating an instance of dog_1 = Dog('Fido',1,True) we can call the talk method fido.talk(). More interestingly though we can call the birthday method from the pet class, fido.birthday(). We can do this since Dog is a subclass of Pet and we say that the class Dog inherits the method talk. Contrastingly we cannot call the talk method for an instantiation of Pet since not all pets are dogs.

In order to discuss the notion of polymorphism let us introduce another subclass of Pet called Cat.

class Cat(Pet):
    
    def talk(self):
        print('Meow')

Note here we don’t specify an __init__ method, since it is called automatically on instantiating a class, and since we do not specify it explicitly it is inherited from the Pet class.

Note we have two subclasses each with a method called talk, which initially might appear worrisome. This demonstrates the notion of polymorphism, that is the same method has different effects on different classes.

I feel like I’ve grasped the notion of classes now, and can begin to see how they might be useful. My next challenge is to use this new knowledge to dive into some machine learning and construct my first home made classifier.