Chapter 8.
Classes and Object-Oriented Programming
be possible to write client code using the specification of Student and have it
work correctly on a TransferStudent.39
Conversely, there is no reason to expect that code written to work for
TransferStudent should work for arbitrary types of Student.
8.3
Encapsulation and Information Hiding
As long as we are dealing with students, it would be a shame not to make them
suffer through taking classes and getting grades.
class Grades(object):
"""A mapping from students to a list of grades"""
def __init__(self):
"""Create empty grade book"""
self.students = []
self.grades = {}
self.isSorted = True
def addStudent(self, student):
"""Assumes: student is of type Student
Add student to the grade book"""
if student in self.students:
raise ValueError('Duplicate student')
self.students.append(student)
self.grades[student.getIdNum()] = []
self.isSorted = False
def addGrade(self, student, grade):
"""Assumes: grade is a float
Add grade to the list of grades for student"""
try:
self.grades[student.getIdNum()].append(grade)
except:
raise ValueError('Student not in mapping')
def getGrades(self, student):
"""Return a list of grades for student"""
try: #return copy of student's grades
return self.grades[student.getIdNum()][:]
except:
raise ValueError('Student not in mapping')
def getStudents(self):
"""Return a list of the students in the grade book"""
if not self.isSorted:
self.students.sort()
self.isSorted = True
return self.students[:] #return copy of list of students
Figure 8.5 Class Grades
39 This substitution principle was first clearly enunciated by Barbara Liskov and
Jeannette Wing in their 1994 paper, A behavioral notion of subtyping.
103