# Illustration of Class Polymorphism and Duck Typing
# send the same method call to objects of many different types,
# each object responds according to its own method definition,
# i.e. same method call takes on “many forms”
class Animal:
def __init__(self, species, name):
self.species = species
self.name = name
def info(self):
print(f'I am a {self.species}. My name is {self.name}')
class Cat(Animal):
def __init__(self, name):
super().__init__('cat', name)
self.sound = 'Meow'
def make_sound(self): # This is polymorphism
print(self.sound)
class Dog(Animal):
def __init__(self, name):
super().__init__('dog', name)
self.sound = 'Bark'
def make_sound(self): # This is polymorphism
print(self.sound)
class Independent_animal:
def __init__(self, name):
self.name = name
def info(self):
print(f'I am {self.name}. I print my own info')
def make_sound(self):
print('I make my own sound')
cat1 = Cat("Kitty")
dog1 = Dog("Fido")
indi1 = Independent_animal('Freedom')
# Duck typing: to iterate these objects together, they do not have to belong to
# the same superclass. As long as each object has info() and make_sound() functions
# they will execute. e.g. indi1 object.
for animal in (cat1, dog1, indi1):
animal.info()
animal.make_sound()
# I am a cat. My name is Kitty
# Meow
# I am a dog. My name is Fido
# Bark
# I am Freedom. I print my own info
# I make my own sound