inheritance: section 9.1, 9.2 victor norman cs106

Post on 27-Dec-2015

220 Views

Category:

Documents

0 Downloads

Preview:

Click to see full reader

TRANSCRIPT

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.

top related