http://www.cs.cornell.edu/courses/cs1110/2019sp 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]
Goal: Make a drawing app Rectangles, Stars, Circles, and Triangles have a lot in common, but they are also different in very fundamental ways… . 2
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 Subclass class Shape(): Superclass Parent class """A shape located at x,y """ Shape Base class def __init__(self, x, y): … def draw(self): … Subclass Rectangle Circle Child class Derived class class Circle(Shape): Shape """An instance is a circle.""" def __init__(self, x, y, radius): … __init__(self,x,y) def draw(self): … draw(self) class Rectangle(Shape): Rectangle(Shape) Circle(Shape) """An in stance is a rectangle. """ def __init__(self, x, y, ht, len): … __init__(self,x,y, ht, len) __init__(self,x,y, radius) draw(self) draw(self) def draw(self): … 4
Extending Classes class < name >(<superclass>): """Class specification""" Class to extend (may need module name: class variables <modulename>.<superclass> ) initializer (__init__) So far, classes have methods implicitly extended object 5
object and the Subclass Hierarchy • Subclassing creates a Example hierarchy of classes built-in class object § Each class has its own super class or parent § Until object at the “top” Shape Super super class • object has many features § Default operators: __ init __, __str__, __eq__ Rectangle Super class Which of these need to be replaced? Square 6
__init__ class Shape(): • Want to use the original version """A shape @ location x,y """ of the method? § New method = original+more def __init__(self, x, y): § Don't repeat code from the original self.x = x • Call old method explicitly self.y = y class Circle(Shape): """Instance is a Circle @ x,y with size radius""" def __init__(self, x, y, radius): self.radius = radius super().__init__(x, y)
Object Attributes can be Inherited class Shape(): c1 id3 id3 """ A shape @ location x,y """ Circle def __init__(self,x,y): x 1 self.x = x Initialized in y 2 self.y = y Shape initializer 4.0 radius class Circle(Shape): """Instance is a Circle @ x,y with size radius""" Initialized in def __init__(self, x, y, radius): Circle initializer self.radius = radius super().__init__(x,y) 8 c1 = Circle(1, 2, 4.0)
More Method Overriding object class Shape(): __init__(self) """Instance is shape @ x,y""" __str__(self) def __init__(self,x,y): __eq__(self) def __str__(self): Shape return "Shape @ ("+str(self.x)+", "+str(self.y)+")" __init__(self,x,y) def draw(self):… __str__(self) Circle class Circle(Shape): """Instance is a Circle @ x,y with radius""” __init__(self,x,y,radius) def __init__(self,x,y,radius): __str__(self) def __str__(self): return "Circle: Radius="+str(self.radius)+" "+super().__str__(self) def draw(self):…
Understanding Method Overriding c1 = Circle(1,2,4.0) object __init__(self) print(str(c1)) __str__(self) __eq__(self) • Which __str__ do we use? Circle(Shape) § Start at bottom class folder __init__(self,x,y) __str__(self) § Find first method with name __eq__(self) § Use that definition draw(self) • Each subclass automatically Circle inherits methods of parent. __init__(self,x,y,radius) __str__(self) • New method definitions __eq__(self) override those of parent. draw(self)
Name Resolution Revisited object • To look up attribute/method name . . . 1. Look first in instance (object folder) Shape() 2. Then look in the class (folder) __init__(self,x,y) • Subclasses add two more rules: draw(self) 3. Look in the superclass 4. Repeat 3. until reach object Circle(Shape) Often called the Bottom–Up Rule __init__(self,x,y, radius) draw(self) c1 = Circle(1,2,4.0) r = c1.radius id3 Circle c1.draw() 2 1 y x c1 id3 4.0 radius 11
Q1: Name Resolution and Inheritance class A(): • Execute the following: >>> a = A() def f(self): return self.g() >>> b = B() • What is value of a.f() ? def g(self): return 10 A: 10 B: 14 class B(A): C: 5 D: ERROR def g(self): E: I don’t know return 14 def h(self): return 18 12
Q2: Name Resolution and Inheritance class A(): • Execute the following: >>> a = A() def f(self): return self.g() >>> b = B() • What is value of b.f() ? def g(self): return 10 A: 10 B: 14 class B(A): C: 5 D: ERROR def g(self): E: I don’t know return 14 def h(self): return 18 13
Accessing the “Original” draw class Shape(): Note: we’ve imported the """Moves pen to correct location""" turtle module which allows def draw(self): us to move a pen on a 2D turtle.penup() grid and draw shapes. turtle.setx(self.x) turtle.sety(self.y) No matter the shape, we turtle.pendown() want to pick up the pen, move to the location of the class Circle(Shape): shape, put the pen down. """Draws Circle""" Only the shape subclasses def draw(self): know how to do the actual super().draw() drawing, though. 14 turtle.circle(self.radius)
Class Variables can also be Inherited class Shape(): # inherits from object by default object """Instance is shape @ x,y""" # Class Attribute tracks total num shapes NUM_SHAPE = 0 Shape(Circle) . . . 0 NUM_SHAPES class Circle(Shape): """Instance is a Circle @ x,y with radius""” Circle # Class Attribute tracks total num circles NUM_ CIRCLE = 0 0 NUM_CIRCLES . . . 15
Q3: Name Resolution and Inheritance class A(): • Execute the following: x = 3 # Class Variable y = 5 # Class Variable >>> a = A() >>> b = B() def f(self): return self.g() • What is value of b.x ? def g(self): A: 4 return 10 B: 3 class B(A): C: 42 y = 4 # Class Variable z = 42 # Class Variable D: ERROR E: I don’t know def g(self): return 14 def h(self): return 18 16
Q4: Name Resolution and Inheritance class A(): • Execute the following: x = 3 # Class Variable y = 5 # Class Variable >>> a = A() >>> b = B() def f(self): return self.g() • What is value of a.z ? def g(self): A: 4 return 10 B: 3 class B(A): C: 42 y = 4 # Class Variable z = 42 # Class Variable D: ERROR E: I don’t know def g(self): return 14 def h(self): return 18 17
The isinstance Function isinstance(<obj>,<class>) object c1 id4 § True if <obj>’s class is same as or a subclass of <class> § False otherwise id4 Circle Example : Shape c1 = Circle(1,2,4.0) 1 x § isinstance(c1,Circle) is True y 2 § isinstance(c1,Shape) is True 4.0 radius Circle § isinstance(c1,object) is True § isinstance(c1,str) is False • Generally preferable to type § Works with base types too! 18
Q5: isinstance and Subclasses object >>> shape1 = Rectangle(0,0,10,10) e id5 >>> isinstance(shape1, Square) ??? Shape id5 Rectangle 1 x A: True Rectangle y 2 B: False C: Error D: I don’t know Square 19
A5: isinstance and Subclasses >>> shape1 = Rectangle(0,0,10,10) object >>> isinstance(shape1, Square) “extends” ??? or “is an instance of” Shape “extends” or “is an instance of” A: True Rectangle B: False C: Error “extends” or “is an instance of” D: I don’t know Square 20
Clicker Answers Q1: A: 10 Q2: B: 14 Q3: B: 3 Q4: D: ERROR Q5: B: False 21
Recommend
More recommend