Inheritance: Section 9.1, 9.2 Victor Norman CS106.
-
Upload
august-day -
Category
Documents
-
view
220 -
download
0
Transcript of Inheritance: Section 9.1, 9.2 Victor Norman CS106.
Inheritance: Section 9.1, 9.2
Victor NormanCS106
The Problem
What is the basic problem that inheritance tries to solve?
Answer:Two types (classes) may have lots of similar code. Inheritance is a way to reuse code, thus removing duplicate code.
Deck and Hand
• Consider: Deck and Hand.• Deck: Hand:– _cards list -- _cards list– addCard() -- addCard()– sort() -- sort()– shuffle() -- shuffle()– getNumCards() -- getNumCards()– removeCard() -- removeCard()
• Lots of similar functionality.
Drawing Man and Womanclass Man: def __init__(self, x, y): self._x = x self._y = y def draw(self): self.drawHead() self.drawBody() self.drawArms() self.drawLegs() def drawHead(self): <code here> def drawLegs(self): <code to draw legs>
class Woman: def __init__(self, x, y): self._x = x self._y = y def draw(self): self.drawHead() self.drawBody() self.drawArms() self.drawLegs() def drawHead(self): <code here> def drawLegs(self): <code to draw skirt>
Lots of duplicate code
• So what? Who cares?
• Duplicate code – more places to make errors– more places to fix errors– inconsistent fixes– more typing– more places to add new code
Solution: a Person class instead of Man/Woman
class Person: def __init__(self, x, y, sex): self._x = x self._y = y self._gender = sex def draw(self): self.drawHead() self.drawBody() self.drawArms() self.drawLegs() def drawHead(self):
<code here> def drawLegs(self): if self._gender == "F": self.drawSkirtAndLegs()
else: self.drawHairyLegs()
def drawHairyLegs(self): <code> def drawSkirtAndLegs(self): <code>
class Man: def __init__(self, x, y): self._x = x self._y = y def draw(self): self.drawHead() self.drawBody() self.drawArms() self.drawLegs() def drawHead(self): <code here> def drawLegs(self): <code to draw legs>
Evaluate this solution
+ Much less code!+ Only 1 class. (Less is almost always better.)− Does not scale as well:Consider: adding Alien now: 3 legs, that bend backwards.def drawLegs(self): if self._gender == “F”: self.drawSkirtAndLegs() elif self._gender == “M”: self.drawHairyLegs() elif self._gender == “A”: self.drawAlienLegs()
Solution: class inheritance
• Keep Person, and make Man, Woman, and Alien be subclasses
Person
Man Woman Alien
Terminology
• Person is the superclass, or base class, or parent class.• Man, Woman, Alien are subclasses, derived classes, or
child classes.• Subclasses inherit from or are derived from
superclasses.
• Want all common attributes and methods “pushed” up the hierarchy.– e.g., Man, Woman, Alien all have x, y location: should be
stored in Person superclass.
Codeclass Person: # an abstract base class. def __init__(self, x_loc, y_loc, gender): self._x = x_loc self._y = y_loc self._gender = gender def draw(self): self.drawHead() self.drawBody() self.drawArms() self.drawLegs() def drawHead(self):
<code here> # NOTE: No drawLegs() code here. Only in # derived classes. Also, don’t really need # to store gender anymore.
Manclass Man(Person): def __init__(self, x_loc, y_loc): Person.__init__(self, x_loc, y_loc, "M")
def drawLegs(self): # code to draw hairy bowlegged legs wearing jeans.
“A Man is-a Person”
Call superclass constructor, passing in
reference to self, location and gender
drawLegs() implemented here – not
in superclass
Woman, Alienfrom person import * # assuming Person is in person.py
class Woman(Person): def __init__(self, x_loc, y_loc): Person.__init__(self, x_loc, y_loc, “F”)
def drawLegs(self): # code to draw legs under a nice modest skirt.
class Alien(Person): def __init__(self, x_loc, y_loc): Person.__init__(self, x_loc, y_loc, "A")
def drawLegs(self): # code to draw 3 legs.
Using this code
(PythonTutor visualization)aaron = Man(10, 20)chris = Woman(30, 40)e_t = Alien(50, 60)
beings = [ aaron, chris, e_t ]for be in beings: be.draw()
Now, you try it!
• We want to create a program that the user can use to draw shapes, etc.
• We need to model these shapes:– Circle– Square– Rectangle– Line– Triangle
• What is the relationship between classes? (the class hierarchy)
• What attributes will each class have?• What methods will each class have?
New class or child class?
Q: If a class needs a couple attributes belonging to another class, is it better to make a child class or a completely new class?
A: If it is just attributes, just make a new class. If it is attributes and a bunch of functionality, make a subclass.
When to subclass?
Q: When would it be better to use the Parent and Child class rather than defining methods in one class?A: 1) You might need to be able to make objects of both kinds of classes. 2) You might have the Parent class well tested – so you don’t want to alter it. 3) You anticipate that you might need another child class of the parent.
SortedSet
Q: I am wondering why a whole separate class is created for some of these functions. For stuff like SortedSet, the case can be made, but I feel like we can accomplish the same thing with a “plain old list” and functions contained in that class.A: I agree. The example is a bit contrived. I would have started from scratch with a class containing a list.
SortedSet (2)
Q: So the "sort" method is created just to prevent people from sorting the already sorted set? And why wouldn't we want to reverse it?A: Right. sort’s code consists of pass. This is done so that it is efficient, instead of trying to sort an already sorted list. You don’t want to reverse it because then it is not sorted anymore.NOTE: when you find you are “undefining” methods provided by the superclass, this should be an indication that you’ve made a poor inheritance decision.
How to see defined methods?
Q: Is there a way to see all the preexisting methods for a parent class?
A: Best way is to do >>> help(class)
in interactive mode.
What does this do?
Q: Are we modifying the class Television or the class DeluxeTV with this def?class DeluxeTV(Television): def __init__(self): Television.__init__(self) self._favorites = [ ]
A: You are modifying the DeluxeTV class – adding _favorites to it.
__setitem__
Q: What is going on with the __setitem__
method?A: __setitem__ is called when you do indexing: __setitem__(...)
x.__setitem__(i, y) <==> x[i]=y
Exampleclass Vic: def __init__(self): self._l = [] def __setitem__(self, loc, item): if len(self._l) > loc: self._l[loc] = item else: numItemsToAdd = loc - len(self._l) for i in range( numItemsToAdd): self._l.append(0) self._l.append(item)
v = Vic()v[0] = "hi"v[3] = "hello"print v._lOUTPUT: ['hi', 0, 0, 'hello']
“Inner” classes
Q: Is it possible to have a class in a class?A: It is possible, but I’ve never had to do it.