Lecture 19: Subclasses & Inheritance · hierarchyof classes §Each class has its own super class or...

Post on 22-Jun-2020

1 views 0 download

Transcript of Lecture 19: Subclasses & Inheritance · hierarchyof classes §Each class has its own super class or...

Lecture 19: Subclasses & Inheritance

(Chapter 18)CS 1110

Introduction to Computing Using Python

[E. Andersen, A. Bracy, D. Gries, L. Lee, S. Marschner, C. Van Loan, W. White]

http://www.cs.cornell.edu/courses/cs1110/2019sp

Goal: Make a drawing app

2

Rectangles, Stars, Circles, and Triangles have a lot in common, but they are also different in very fundamental ways….

Sharing Work

Problem: Redundant code.(Any time you copy-and-paste code, you are likely doing something wrong.)

Solution: Create a parent class with shared code§ Then, create subclasses of the parent class

3

Defining a Subclassclass Shape():

"""A shape located at x,y """def __init__(self, x, y): …def draw(self): …

class Circle(Shape):"""An instance is a circle."""def __init__(self, x, y, radius): …def draw(self): …

class Rectangle(Shape):"""An in stance is a rectangle. """def __init__(self, x, y, ht, len): …def draw(self): …

Shape

Rectangle Circle

__init__(self,x,y)draw(self)

Shape

__init__(self,x,y, ht, len)draw(self)

Rectangle(Shape)

__init__(self,x,y, radius)draw(self)

Circle(Shape)

SuperclassParent classBase class

SubclassChild classDerived class

4

Extending Classes

class <name>(<superclass>):"""Class specification"""class variablesinitializer (__init__)methods So far, classes have

implicitly extended object

Class to extend(may need module name:

<modulename>.<superclass>)

5

object and the Subclass Hierarchy

• Subclassing creates a hierarchy of classes§ Each class has its own

super class or parent§ Until object at the “top”

• object has many features§ Default operators:

__init__, __str__, __eq__Which of these need to be replaced?

Super class

Super super class

built-in class

6

Example

object

Shape

Rectangle

Square

__init__class Shape():

"""A shape @ location x,y """ def __init__(self, x, y):

self.x = xself.y = y

class Circle(Shape):"""Instance is a Circle @ x,y with size radius"""

def __init__(self, x, y, radius):self.radius = radiussuper().__init__(x, y)

• Want to use the original version of the method?§ New method = original+more§ Don't repeat code from the original

• Call old method explicitly

Object Attributes can be Inherited

id3Circle

y 2x 1

radius 4.0

Initialized inCircle

initializer

8

class Shape():""" A shape @ location x,y """ def __init__(self,x,y):

self.x = xself.y = y

class Circle(Shape):"""Instance is a Circle @ x,y with size radius"""def __init__(self, x, y, radius):

self.radius = radiussuper().__init__(x,y)

Initialized inShape

initializer

c1 = Circle(1, 2, 4.0)

c1 id3

More Method Overridingclass Shape():

"""Instance is shape @ x,y""" def __init__(self,x,y):def __str__(self):

return "Shape @ ("+str(self.x)+", "+str(self.y)+")"def draw(self):…

class Circle(Shape):"""Instance is a Circle @ x,y with radius""”def __init__(self,x,y,radius):def __str__(self):

return "Circle: Radius="+str(self.radius)+" "+super().__str__(self)def draw(self):…

__init__(self)__str__(self)__eq__(self)

object

__init__(self,x,y)__str__(self)

Shape

__init__(self,x,y,radius)__str__(self)

Circle

Understanding Method Overriding

__init__(self)__str__(self)__eq__(self)

object

__init__(self,x,y)__str__(self)__eq__(self)draw(self)

Circle(Shape)

__init__(self,x,y,radius)__str__(self)__eq__(self)draw(self)

Circle

c1 = Circle(1,2,4.0)print(str(c1))

• Which __str__ do we use?§ Start at bottom class folder§ Find first method with name§ Use that definition

• Each subclass automatically inherits methods of parent.

• New method definitions override those of parent.

11

Name Resolution Revisited• To look up attribute/method name

1. Look first in instance (object folder)2. Then look in the class (folder)

• Subclasses add two more rules:3. Look in the superclass4. Repeat 3. until reach object

Often called the Bottom–Up Rule

radius 4.0

id3

y 2x 1c1 id3Circle

. . . object

__init__(self,x,y, radius)draw(self)

Circle(Shape)

__init__(self,x,y)draw(self)

Shape()

c1 = Circle(1,2,4.0)r = c1.radiusc1.draw()

Q1: Name Resolution and Inheritanceclass A():

def f(self):return self.g()

def g(self):return 10

class B(A):

def g(self):return 14

def h(self):return 18

• Execute the following:>>> a = A()>>> b = B()

• What is value of a.f()?

12

A: 10B: 14C: 5D: ERRORE: I don’t know

Q2: Name Resolution and Inheritance

• Execute the following:>>> a = A()>>> b = B()

• What is value of b.f()?

13

A: 10B: 14C: 5D: ERRORE: I don’t know

class A():

def f(self):return self.g()

def g(self):return 10

class B(A):

def g(self):return 14

def h(self):return 18

Accessing the “Original” draw

14

class Shape():"""Moves pen to correct location""" def draw(self):

turtle.penup()turtle.setx(self.x)turtle.sety(self.y)turtle.pendown()

class Circle(Shape):"""Draws Circle"""

def draw(self):super().draw()turtle.circle(self.radius)

Note: we’ve imported the turtle module which allows us to move a pen on a 2D grid and draw shapes.

No matter the shape, we want to pick up the pen, move to the location of the shape, put the pen down. Only the shape subclasses know how to do the actual drawing, though.

Class Variables can also be Inherited

class Shape(): # inherits from object by default"""Instance is shape @ x,y""" # Class Attribute tracks total num shapesNUM_SHAPE = 0. . .

class Circle(Shape):"""Instance is a Circle @ x,y with radius""”# Class Attribute tracks total num circlesNUM_ CIRCLE = 0. . .

object

NUM_SHAPES

Shape(Circle)

NUM_CIRCLES

Circle

0

0

15

Q3: Name Resolution and Inheritance

• Execute the following:>>> a = A()>>> b = B()

• What is value of b.x?

16

A: 4B: 3C: 42D: ERRORE: I don’t know

class A():x = 3 # Class Variable y = 5 # Class Variable

def f(self):return self.g()

def g(self):return 10

class B(A):y = 4 # Class Variable z = 42 # Class Variable

def g(self):return 14

def h(self):return 18

Q4: Name Resolution and Inheritance

• Execute the following:>>> a = A()>>> b = B()

• What is value of a.z?

17

A: 4B: 3C: 42D: ERRORE: I don’t know

class A():x = 3 # Class Variable y = 5 # Class Variable

def f(self):return self.g()

def g(self):return 10

class B(A):y = 4 # Class Variable z = 42 # Class Variable

def g(self):return 14

def h(self):return 18

The isinstance Function

isinstance(<obj>,<class>)§ True if <obj>’s class is same as or

a subclass of <class> § False otherwise

Example:c1 = Circle(1,2,4.0)

§ isinstance(c1,Circle) is True§ isinstance(c1,Shape) is True§ isinstance(c1,object) is True§ isinstance(c1,str) is False

• Generally preferable to type§ Works with base types too! 18

c1 id4

id4Circle

object

Shape

Circleradius 4.0y 2

x 1

Q5: isinstance and Subclasses

>>> shape1 = Rectangle(0,0,10,10)>>> isinstance(shape1, Square)???

19

A: TrueB: FalseC: ErrorD: I don’t know

e id5

id5Rectangle

object

Shape

Rectangle

y 2

x 1

Square

A5: isinstance and Subclasses

>>> shape1 = Rectangle(0,0,10,10)>>> isinstance(shape1, Square)???

20

A: TrueB: FalseC: ErrorD: I don’t know

object

Rectangle

Shape

“extends” or “is an instance of”

Square

“extends” or “is an instance of”

“extends” or “is an instance of”

Clicker Answers

Q1: A: 10Q2: B: 14Q3: B: 3Q4: D: ERRORQ5: B: False

21