Example code - Inheritance issues
The challenges in inheritance can not be demonstrated well in a powerpoint. Thus, I made this page with examples. You can copy the code in the section and add it together and run it.
First I create a slightly bigger CatClass.
class CatClass:
### Class variables
genus = "Felis"
species = "Catus"
acts = {'scratch': "purrs",
'scare': "jumps high in the air",
'feed': "is very excited" }
### Instatiation
def __init__(self, name, gender):
self.name, self.gender = name, gender
### Magic methods
# Addition makes a kitten if male and female cat, alternative constructor
def __add__(self, other):
# Taken a short cut and just demanding the genders to be different to breed
if self.gender == other.gender:
return NotImplemented
# Being biased and saying all kittens are male
kitten = CatClass('Unnamed kitten', 'male')
return kitten
### Class methods
# Adding a cat action
@classmethod
def add_action(cls, action, reaction):
cls.acts[action] = reaction
# Querying class for number of actions
@classmethod
def count_action(cls):
return len(cls.acts)
### Property methods
# age setter and getter
@property
def age(self):
if not hasattr(self, '_age'):
raise NameError("Age of cat is not yet set")
return self._age
@age.setter
def age(self, value):
if value < 0:
raise ValueError("Age can not be negative")
self._age = value
### Instance methods
# The action method - using class variables
def action(self, act):
if act in CatClass.acts:
print(self.name, CatClass.acts[act])
elif self.gender == 'male':
print(self.name, "looks bored")
else:
print(self.name, "yawns")
### Main program
yourcat = CatClass('Missy', 'female')
yourcat.age = 5
print(f"The age of your cat is {yourcat.age}")
CatClass.add_action("annoy", "scratches your face")
print("Actions in CatClass:", CatClass.count_action())
mycat = CatClass("Tom", "male")
kitten = mycat + yourcat
print(f"Kitten: {kitten.name}")
yourcat.action('scare')
This class looks fine, but it has a number of inheritance issues. By creating a Tiger class that inherits from the CatClass, I will demonstrate. Also, see how simple it was to create a new class based on an old :-)
class Tiger(CatClass):
acts = {
'scratch': 'roars',
'feed': 'demands more meat'
}
tigger = Tiger("Shere Khan", "male")
tigger.action("scratch")
tigger.action('scare')
We want the Tiger to react differently than the Cat, at least for some actions. However, this code does not do it. The problem lies in the inherited action method.
def action(self, act):
if act in CatClass.acts:
print(self.name, CatClass.acts[act])
elif self.gender == 'male':
print(self.name, "looks bored")
else:
print(self.name, "yawns")
# We are specifically using the actions in the CatClass for the behavior
# We need to use the current class, as in cat uses CatClass actions and tigers uses Tiger actions.
# These are the problematic lines, they can be replaced in different ways
if act in CatClass.acts:
print(self.name, CatClass.acts[act])
# Through '''self''', as self will search for the instance namespace and then the class namespace for the variable
if act in self.acts:
print(self.name, self.acts[act])
# Dynamically getting the class by type
cls = type(self)
if act in cls.acts:
print(self.name, cls.acts[act])