In this lab, we’ll explore more fundamental OOP concepts starting with generalisation and inheritance. We'll use a practical example involving plants to understand these concepts. You'll see how we can create a general blueprint for all plants and then extend this blueprint to accommodate specific types of plants like flowers, trees, and cacti.
By the end of this lab, you'll start applying what you’ve learned to create your own "Animal Kingdom" program. This will not only reinforce the concepts but also help you see how they can be applied to different scenarios in programming.
Ensure that you are signed into your GitHub account
Join the GitHub Classroom and accept this assignment: Project 10 - Animal Kingdom
Clone the repository to your computer using GitHub Desktop or open it online using Codespaces
Generalisation is a cornerstone of object-oriented programming. It involves identifying the common characteristics and behaviors of objects and defining them in a general class. This process helps in creating a blueprint that can be used to build more specific classes.
All plants share some basic characteristics and behaviors (as far as I know). For example, every plant:
Has a name.
Has an age.
Lives in a specific habitat.
Can perform photosynthesis.
Grows over time.
These commonalities allow us to define a general class that represents all plants, which can then be specialised for particular types of plants.
Using the general characteristics identified in our discussion on generalisation, we can now create a base class called Plant. This class will encapsulate the common attributes and behaviors that all plants share. Here's how we can define this class in Python:
class Plant:
def __init__(self, name, age, habitat):
self.name = name
self.age = age
self.habitat = habitat
def photosynthesize(self):
return f"{self.name} is photosynthesizing."
def grow(self):
return f"{self.name} grows a little every day."
The __init__ method initialises each plant object with basic attributes: name, age, and habitat.
photosynthesize and grow are methods that define common behaviors all plants can perform.
This base class serves as the foundation upon which we will build more specific plant classes like Flower, Tree, and Cactus.
Inheritance is an essential concept in object-oriented programming that allows a new class (called a derived or child class) to inherit attributes and methods from an existing class (called a base or parent class). This mechanism promotes code reuse and can help manage complexity in software development.
While all plants share some common characteristics, they also have unique features. For example:
Flowers might have a specific color and the ability to bloom.
Trees typically grow to much larger sizes and may shed leaves annually.
Cacti are adapted to store water and thrive in arid environments.
These differences are perfect candidates for demonstrating inheritance, where specialised classes inherit common features from the Plant base class but also introduce their own unique properties and behaviors.
Building on our base Plant class, we can now create several derived classes that represent different types of plants.
Each of these will extend the base class with its unique attributes and methods.
class Flower(Plant):
def __init__(self, name, age, habitat, color):
super().__init__(name, age, habitat)
self.color = color
def bloom(self):
return f"{self.name}, a {self.color} flower, blooms beautifully!"
class Tree(Plant):
def __init__(self, name, age, habitat, height):
super().__init__(name, age, habitat)
self.height = height
def shed_leaves(self):
return f"{self.name} sheds its leaves for the season."
class Cactus(Plant):
def __init__(self, name, age, habitat, has_flowers):
super().__init__(name, age, habitat)
self.has_flowers = has_flowers
def store_water(self):
return f"{self.name} stores water to survive the dry period."
In the derived class constructors, you might notice the use of super(). This function is crucial as it allows the child class to call methods from the parent class, which in this case, is to initialise inherited attributes.
Initialisation Reuse: It helps in reusing the initialisation code of the parent class without rewriting it.
Maintainability: Makes the code easier to maintain, as changes to the parent class constructor need to be made only in one place.
Here, we show (using solid arrows) that Flower, Tree and Cactus are inherited from Plant.
Now that we have our base class and derived classes defined, let’s see how to create instances of these classes and invoke their methods:
Open lab1.py
Complete the following activities:
Create a class named Animal that represents a generic animal in an animal kingdom.
This class should have an initialiser with at least three attributes. E.g. name, age, and habitat.
Add at least two methods for common animal behaviors. E.g. eat and sleep.
Create at least two derived classes from the Animal class. E.g. Bird and Fish.
Give each of the derived classes at least one specific behavior. E.g. fly and swim.
Create at least two instances of the Animal derived classes with different data.
Write code that prints out the details of each animal and calls their specific behaviors.
Commit and push your code