http://www.cs.cornell.edu/courses/cs1110/2018sp 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]
Announcements • More recursion examples on the Lectures page • A3 is being graded this week • A4 coming soon! • Prelim 2 § Tuesday, April 24 th , 7:30-9:00pm § Please go to the same room you went for Prelim 1 § Conflicts assignment on CMS, due 11:59pm Thurs. • Lab 11 is out (there is no Lab 10) 2
Goal: Make a drawing app Rectangles, Stars, Circles, and Triangles have a lot in common, but they are also different in very fundamental ways… . 3
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 4
Defining a Subclass class Shape(): Superclass Parent class Shape """A shape located at x,y """ 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): … 5
Extending Classes class < name >(<superclass>): """Class specification""" Class to extend (may need module name) class variables initializer (__init__) So far, classes have methods implicitly extended object 6
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__ , Rectangle __repr__, __eq__ Super class Which of these need to be replaced? Square 7
__init__ class Shape(): • Want to use the original """Instance is shape @ x,y""" version of the method? § New method = original+more def __init__(self, x, y): § Do not want to repeat code self.x = x from the original version self.y = y • Call old method explicitly class Circle(Shape): """Instance is a Circle @ x,y with radius""” def __init__(self, x, y, radius): self.radius = radius super().__init__(x, y)
Object Attributes can be Inherited class Shape(): c1 id3 id3 """Instance is shape @ 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 radius""” Initialized in def __init__(self, x, y, radius): Circle initializer self.radius = radius super().__init__(x,y) 9 c1 = Circle(1, 2, 4.0)
More Method Overriding object class Shape(): double __init__(self) underscore """Instance is shape @ x,y""" __str__(self) methods are def __init__(self,x,y): __eq__(self) in class object 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)+" "+Shape.__str__(self) def draw(self):…
Understanding Method Overriding object c1 = Circle(1,2,4.0) __init__(self) print(str(c1)) __str__(self) __eq__(self) • Which __str__ do we use? 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) • Subclasses add two more rules: __init__(self,x,y) 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 12
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 13
A1: 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 CORRECT B: 14 class B(A): C: 5 D: ERROR def g(self): E: I don’t know return 14 def h(self): return 18 14
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 15
A2: 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 CORRECT class B(A): C: 5 D: ERROR def g(self): E: I don’t know return 14 def h(self): return 18 16
Accessing the “Original” draw class Shape(): Note: we’ve imported the turtle module which def draw(self): turtle.penup() allows us to move a pen on turtle.setx(self.x) a 2D grid and draw shapes. 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. def draw(self): Only the shape subclasses super().draw() know how to do the actual turtle.circle(self.radius) drawing, though. 17
Class Variables can also be Inherited object class Shape(object): """Instance is shape @ x,y""" # Class Attribute Shape NUM_SHAPES = 0 . . . 0 NUM_SHAPES class Circle(Shape): """Instance is a Circle @ x,y with radius""” Circle # Class Attribute 0 NUM_CIRCLES NUM_CIRCLES = 0 . . . 18
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 19
A3: 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 CORRECT 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 20
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 21
A4: 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 CORRECT E: I don’t know def g(self): return 14 def h(self): return 18 22
Why override __eq__ ? class Shape(): """Instance is shape @ x,y""" def __init__(self,x,y): def __eq__(self, other): """If position is the same, then equal as far as Shape knows""" return self.x == other.x and self.y == other.y class Circle(Shape): """Instance is a Circle @ x,y with radius""” def __init__(self,x,y,radius): def __eq__(self, other): """If radii are equal, let super do the rest""" return self.radius == other.radius and super().__eq__(other)
eq vs. is == compares equality id4 is compares identity Circle id4 c1 1 x c1 = Circle(1, 1, 25) y 1 c2 id5 c2 = Circle(1, 1, 25) radius 25 c3 = c2 id5 c3 id5 Circle c1 == c2 ? x 1 c1 is c2 ? 1 y c2 == c3 ? 25 radius c2 is c3 ?
Recommend
More recommend