Inheritance: Section 9.1, 9.2 Victor Norman CS106.

23
Inheritance: Section 9.1, 9.2 Victor Norman CS106

Transcript of Inheritance: Section 9.1, 9.2 Victor Norman CS106.

Page 1: Inheritance: Section 9.1, 9.2 Victor Norman CS106.

Inheritance: Section 9.1, 9.2

Victor NormanCS106

Page 2: Inheritance: Section 9.1, 9.2 Victor Norman CS106.

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.

Page 3: Inheritance: Section 9.1, 9.2 Victor Norman CS106.

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.

Page 4: Inheritance: Section 9.1, 9.2 Victor Norman CS106.

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>

Page 5: Inheritance: Section 9.1, 9.2 Victor Norman CS106.

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

Page 6: Inheritance: Section 9.1, 9.2 Victor Norman CS106.

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>

Page 7: Inheritance: Section 9.1, 9.2 Victor Norman CS106.

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()

Page 8: Inheritance: Section 9.1, 9.2 Victor Norman CS106.

Solution: class inheritance

• Keep Person, and make Man, Woman, and Alien be subclasses

Person

Man Woman Alien

Page 9: Inheritance: Section 9.1, 9.2 Victor Norman CS106.

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.

Page 10: Inheritance: Section 9.1, 9.2 Victor Norman CS106.

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.

Page 11: Inheritance: Section 9.1, 9.2 Victor Norman CS106.

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

Page 12: Inheritance: Section 9.1, 9.2 Victor Norman CS106.

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.

Page 13: Inheritance: Section 9.1, 9.2 Victor Norman CS106.

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()

Page 14: Inheritance: Section 9.1, 9.2 Victor Norman CS106.

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?

Page 15: Inheritance: Section 9.1, 9.2 Victor Norman CS106.

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.

Page 16: Inheritance: Section 9.1, 9.2 Victor Norman CS106.

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.

Page 17: Inheritance: Section 9.1, 9.2 Victor Norman CS106.

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.

Page 18: Inheritance: Section 9.1, 9.2 Victor Norman CS106.

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.

Page 19: Inheritance: Section 9.1, 9.2 Victor Norman CS106.

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.

Page 20: Inheritance: Section 9.1, 9.2 Victor Norman CS106.

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.

Page 21: Inheritance: Section 9.1, 9.2 Victor Norman CS106.

__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

Page 22: Inheritance: Section 9.1, 9.2 Victor Norman CS106.

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']

Page 23: Inheritance: Section 9.1, 9.2 Victor Norman CS106.

“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.