Nov 4

Lecture Overview

Inheritance Design

import turtle

class GeometricObject:
    def __init__(self):
        self.line_color = 'black'
    def get_color(self):
        return self.line_color
    def set_color(self, c):
        self.line_color = c

# A point is a geometric object, so we derive from it
class Point(GeometricObject):
    def __init__(self, x, y):
        super().__init__()
        self.x = x
        self.y = y

    def draw(self):
        turtle.goto(self.x, self.y)
        turtle.dot(1, self.get_color())

# A polygon is a geometric object, so we derive from it
class Polygon(GeometricObject):
    def __init__(self):
        super().__init__()
        # For a polygon, we store it as a list of points initially empty
        self.points = []

    def add_point(self, p):
        self.points.append(p)

    def draw(self):
        if len(self.points) == 0:
            return
        turtle.color(self.get_color())
        for p in self.points:
            turtle.goto(p[0], p[1])
            turtle.down()
        # Go back to the start
        turtle.goto(self.points[0][0], self.points[1][1])
        turtle.up()

# A rectangle is a polygon, so we derive from it
class Rectangle(Polygon):
    def __init__(self, x, y, width, height):
        super().__init__()
        self.add_point( (x, y) )
        self.add_point( (x + width, y) )
        self.add_point( (x + width, y + height) )
        self.add_point( (x, y + height) )

    # The add_point method causes a "Circle-ellipse problem" and therefore violates
    # the Liskov substitution principle, since it does not make sense to add a point
    # to a rectangle.


# A canvas has many geometric objects, so we store them in a property
class Canvas:
    def __init__(self):
        self.geo = []

    def add(self, obj):
        self.geo.append(obj)

    def draw(self):
        for g in self.geo:
            g.draw()

turtle.setworldcoordinates(-5, -5, 5, 5)
turtle.up()
canvas = Canvas()

canvas.add(Rectangle(1, 2, 0.5, 0.7))
canvas.add(Point(-1, -3))

r = Rectangle(-1, 4, 2, 1)
r.set_color("green")
canvas.add(r)

canvas.draw()
input("Press enter")

Super

Each class in python is itself an object with information about the methods and base classes. The super function (used above) allows access to this information and in partiuclar allows you to call methods that are defined on your base class. I used it above to call the __init__ method on the superclass or parent class, so inside Point initialization, I call the geometric object initialization method as the first step.

Exercises

           |\
           | \
           |  \
           |   \
           |    \
           |     \
           |      \
           |       \
           |      α \
(x, y) ->  ----------
              base

You will need to use the math module trig functions to compute the top corner inside the initialization method: remember that the math module uses radians and pi is available at math.pi.