OBJECT-ORIENTED
PROGRAMMING 2
CS5800: Lecture 7
1
Learning Objectives
• Why use objects?
• getter and setter methods
• Information hiding
• Hierarchies, inheritance
• Class variables
WHY USE OOP AND
CLASSES OF OBJECTS?
• mimic real life
• group different objects part of the same type
Image Credits, clockwise from top: Image Courtesy Harald Wehner, in the public Domain. Image Courtesy MTSOfan, CC-BY-NC-SA. Image Courtesy Carlos Solana, license CC-
BY-NC-SA. Image Courtesy Rosemarie Banghart-Kovic, license CC-BY-NC-SA. Image Courtesy Paul Reynolds, license CC-BY. Image Courtesy Kenny Louie, License CC-BY
3
6.0001 LECTURE 9 6
GETTER AND SETTER METHODS
class Animal(object):
def __init__(self, age):
self.age = age
self.name = None
def getAge(self):
return self.age
def getName(self):
return self.name
def setAge(self, newage):
self.age = newage
def setName(self, newname=""):
self.name = newname
4
GETTER AND SETTER METHODS
class Animal(object):
def __init__(self, age):
self.age = age
self.name = None
def getAge(self):
return self.age getters
def getName(self):
return self.name
def setAge(self, newage):
self.age = newage
def setName(self, newname=""):
self.name = newname
5
GETTER AND SETTER METHODS
class Animal(object):
def __init__(self, age):
self.age = age
self.name = None
def getAge(self):
return self.age setters
def getName(self):
return self.name
def setAge(self, newage):
self.age = newage
def setName(self, newname=""):
self.name = newname
6
Go to Moodle quiz “getters and setters”
INSTANCE AND DOT NOTATION
Instantiation creates an instance of an object
a = Animal(3)
Dot notation used to access attributes (data and
methods)
a.age
It is better to use getters and setters to access
data attributes
a.getAge()
8
INFORMATION HIDING
Author of class definition may change data attribute variable names
class Animal(object):
def __init__(self, age):
self.years = age
def getAge(self):
return(self.years)
If you are accessing data attributes outside the class and class
definition changes, may get errors
Outside of class, use getters and setters instead use a.getAge() NOT
a.age
◦ good style
◦ easy to maintain code
◦ prevents bugs
9
PYTHON NOT GREAT AT
INFORMATION HIDING
allows you to access data from outside class definition
print(a.age)
allows you to write to data from outside class definition
a.age = 'infinite'
allows you to create data attributes for an instance from
outside class definition
a.size = "tiny"
it s not good style to do any of these!
10
Go to Moodle quiz “hidden variables”
DEFAULT ARGUMENTS
Default arguments for formal parameters are used if no
actual argument is given
def setName(self, newname=""):
self.name = newname
Default argument used here
a = Animal(3)
a.setName()
print(a.getName())
Argument passed in is used here
a = Animal(3)
a.setName("fluffy")
print(a.getName())
12
DEFAULT ARGUMENTS
Default arguments for formal parameters are used if no
actual argument is given
def setName(self, newname=""):
self.name = newname
Default argument used here
a = Animal(3)
a.setName() prints ""
print(a.getName())
Argument passed in is used here
a = Animal(3)
a.setName("fluffy")
print(a.getName())
13
DEFAULT ARGUMENTS
Default arguments for formal parameters are used if no
actual argument is given
def setName(self, newname=""):
self.name = newname
Default argument used here
a = Animal(3)
a.setName()
print(a.getName())
Argument passed in is used here
a = Animal(3)
a.setName("fluffy") prints "fluffy"
print(a.getName())
14
Go to Moodle quiz “default arguments”
HIERARCHIES l s
HIERARCHIES An im a
Image Credits, clockwise from top: Image Courtesy Deeeep, CC-BY-NC. Image Image Courtesy MTSOfan, CC-BY-NC-SA. Image Courtesy Carlos Solana, license CC-BY-NC-SA.
Image Courtesy Rosemarie Banghart-Kovic, license CC-BY-NC-SA. Image Courtesy Paul Reynolds, license CC-BY. Image Courtesy Kenny Louie, License CC-BY. Courtesy
Harald Wehner, in the public Domain.
16
6.0001 LECTURE 9 14
HIERARCHIES
parent class
(superclass) Animal
child class
(subclass)
• inherits all data Person Cat Rabbit
and behaviors of
parent class
• add more info
• add more behavior Student
• override behavior
6.0001 LECTURE 9 15
17
INHERITANCE: PARENT CLASS
class Animal(object):
def __init__(self, age):
self.age = age
self.name = None
def getAge(self):
return self.age
def getName(self):
return self.name
def setAge(self, newage):
self.age = newage
def setName(self, newname=""):
self.name = newname
def __str__(self):
return(“animal:”+str(self.name)+":"+str(self.age))
18
INHERITANCE: PARENT CLASS
• everything is an object
class Animal(object): • class object implements basic
def __init__(self, age): operations in Python, e.g.,
self.age = age binding variables, etc.
self.name = None
def getAge(self):
return self.age
def getName(self):
return self.name
def setAge(self, newage):
self.age = newage
def setName(self, newname=""):
self.name = newname
def __str__(self):
return "animal:"+str(self.name)+":"+str(self.age)
19
INHERITANCE: SUBCLASS
class Cat(Animal):
def speak(self):
print("meow")
def __str__(self):
return "cat:"+str(self.name)+":"+str(self.age)
20
INHERITANCE: SUBCLASS
class Cat(Animal):
def speak(self):
print("meow")
def __str__(self):
return "cat:"+str(self.name)+":"+str(self.age)
Inherits all attributes of Animal:
✦
__init__()
✦
age
✦
name
✦
getAge()
✦
getName()
✦
setAge()
✦
setName()
✦
__str__()
21
INHERITANCE: SUBCLASS
class Cat(Animal):
def speak(self):
print("meow")
def __str__(self):
return "cat:"+str(self.name)+":"+str(self.age)
Add new functionality Inherits all attributes of Animal:
via speak() method ✦
__init__()
✦
age
✦
name
✦
getAge()
✦
getName()
✦
setAge()
✦
setName()
✦
__str__()
22
INHERITANCE: SUBCLASS
class Cat(Animal):
def speak(self):
print("meow")
def __str__(self):
return "cat:"+str(self.name)+":"+str(self.age)
Add new functionality Inherits all attributes of Animal:
via speak() method ✦
__init__()
✦
age
✦
name
✦
getAge()
Override ✦
getName()
__str__() ✦
setAge()
method ✦
setName()
✦
__str__()
23
INHERITANCE: SUBCLASS
class Cat(Animal):
def speak(self):
print("meow")
def __str__(self):
return "cat:"+str(self.name)+":"+str(self.age)
Inherit functionality of the parent class
◦ __init__() is not missing, uses the Animal version
Specialise with new functionality: speak()
◦ Instance of type Cat can be called with new methods
◦ Instance of type Animal throws error if called with
Cat’s new method
Override functionality of the parent class
24
Go to Moodle quiz “Hierarchy”
WHICH METHODS TO USE
Subclass can have methods with same name as
superclass (overridden methods)
Given an instance of a class, look for a method
name in current class definition
If not found, look for method name up the
hierarchy (in parent, then grandparent, etc.)
Use first method up the hierarchy that you found
with that method name
26
class Person(Animal): Parent class is Animal
def __init__(self, name, age):
Call Animal constructor
Animal.__init__(self, age)
self.setName(name) Call Animal's method
self.friends = []
Add a new data attribute
def get_friends(self):
return(self.friends)
def speak(self): New methods
print("hello")
def add_friend(self, fname):
if fname not in self.friends:
self.friends.append(fname)
def age_diff(self, other):
diff = self.age - other.age
Override Animal's
print(abs(diff), "year difference") __str__() method
def __str__(self):
return(“person:”+str(self.name)+":"+str(self.age))
27
import random
Inherits Person and
class Student(Person): Animal attributes
def __init__(self, name, age, degree=None):
Person.__init__(self, name, age)
self.degree = degree Adds new data attribute
def change_degree(self, degree):
self.degree = degree
def speak(self):
r = random.random() Calls random() method of class
Random
if r < 0.25:
Return float in [0,1)
print("I have homework")
elif 0.25 <= r < 0.5:
print("I need sleep")
elif 0.5 <= r < 0.75:
print("I should eat")
else:
print(“I am watching tv")
def __str__(self):
return(“student:”+str(self.name)+":"+str(self.age)+":"+str(self.degree))
28
Go to Moodle quiz “Extend class”
CLASS VARIABLES
class variables and their values are shared
between all instances of a class
class Rabbit(Animal): Parent class is Animal
# a class variable, tag, shared across all instances
tag = 1 Class variable
def __init__(self, age, parent1=None, parent2=None):
Animal.__init__(self, age)
Access class
Instance self.parent1 = parent1 variable
variable
self.parent2 = parent2
self.rid = Rabbit.tag Incrementing class variable
Rabbit.tag += 1 changes it for all instances
that may reference it
tag used to give unique id to each new Rabbit instance
30
Rabbit GETTER METHODS
class Rabbit(Animal):
# a class variable, tag, shared across all instances
tag = 1
def __init__(self, age, parent1=None, parent2=None):
Animal.__init__(self, age)
self.parent1 = parent1
self.parent2 = parent2 Method on a string to
pad the beginning with
self.rid = Rabbit.tag 0's, e.g., 001, not 1
Rabbit.tag += 1
def getRid(self):
return str(self.rid).zfill(3) ✴ Getter methods specific
for the Rabbit class
def getParent1(self):
✴ getName() and
return self.parent1 getAge() are inherited
def getParent2(self): from Animal
return self.parent2
31
CUSTOMISING YOUR OWN TYPES
def __add__(self, other):
# returning object of same type as this class
return Rabbit(0, self, other)
Recall Rabbit's __init__(self, age, parent1=None, parent2=None)
Define (override) + operator between two Rabbit instances
◦ Define what something like this does: r4 = r1 + r2 where
r1 and r2 are Rabbit instances
◦ r4 is a new Rabbit instance with age 0
◦ r4 has self as one parent and other as the other parent
◦ in __init__, parent1 and parent2 are of type Rabbit
32
SPECIAL METHOD TO COMPARE
TWO RABBITS
Decide that two rabbits are equal if they have the
same two parents
Compare ids of parents since ids are unique
(due to class var)
booleans
def __eq__(self, other):
parentSame = self.parent1.rid == other.parent1.rid \
and self.parent2.rid == other.parent2.rid
parentsOpposite = self.parent2.rid == other.parent1.rid \
and self.parent1.rid == other.parent2.rid
return(parentsSame or parentsOpposite)
33
Go to Moodle quiz “Class variable”
MORE CUSTOMISATION
class Vector(object): 2D Euclidean vector
def __init__(self, x, y):
self.x = x Computes the magnitude 2 2
self.y = y of the vector x + y
def magnitude(self):
return (self.x**2 + self.y**2)**(0.5)
def __abs__(self): Overload abs() function
return self.magnitude()
def __add__(self, other): Overload + operator
return Vector(self.x + other.x, self.y + other.y)
v1 = Vector(3, 4)
print(abs(v1)) # Calls Vector.__abs__(v1)
v2 = Vector(-1, -2)
v3 = v1 + v2 # Calls Vector.__add__(v1, v2)
print(v3)
35
MORE CUSTOMISATION
class Vector(object): 2D Euclidean vector
def __init__(self, x, y):
self.x = x Computes the magnitude 2 2
self.y = y of the vector x + y
def magnitude(self):
return (self.x**2 + self.y**2)**(0.5)
def __abs__(self): Overload abs() function
return self.magnitude()
def __add__(self, other): Overload + operator
return Vector(self.x + other.x, self.y + other.y)
v1 = Vector(3, 4)
print(abs(v1)) # Calls v1.__abs__()
v2 = Vector(-1, -2)
v3 = v1 + v2 # Calls v1.__add__(v2)
print(v3)
36
POWER OF OOP
Bundle data and operations that work on them together
through well-defined interfaces
Divide-and-conquer development
◦ implement and test behaviour of each class separately
◦ increased modularity reduces complexity
Classes make it easy to reuse code
◦ many Python modules define new classes
◦ each class has a separate environment (no collision on
function names)
◦ inheritance allows subclasses to redefine or extend a
selected subset of a superclass’ behaviour
37
POWER OF OOP
Bundle data and operations that work on them
together through well-defined interfaces
Organise information
Division of work
Access information in a consistent manner
Add layers of complexity
Like functions, classes are a mechanism for
decomposition, abstraction, and reuse in
programming
38
self is this class object
self is an arbitrary instance of this class
self is a reserved Python keyword
self is a convention used to refer to an arbitrary
instance of this class
self is automatically assigned a value when a
method is called on an instance via the "dot"
notation
39