< Back

Lecture 9- Inheritance


As usual, create a directory to hold today's activities:

$ mkdir ~/cs170/labs/lab9 
$ cd ~/cs170/labs/lab9

An Introduction to Inheritance

We now understand how classes can represent our own data types. This is incredibly neat, and even allows for the efficient reuse of code. However, there are some instance where your current knowledge of classes would cause your code to not be very reusable. For example, what if something doesn't fit exactly into the templates we've created for our objects? One mechanism to fix this problem is inheritance, which allows us to specify the relationships between classes.


Lab Activity
Dogs

One of the more classical examples of Inheritance is describing animals. There is a well known hierarchy of animals, based off of genus, species, phylum, etc. However, that can be a little bit complicated and overwhelming. So, we'll focus on one common type of animal: dogs.

This is a very simplistic, directed, and less that useful example of inheritance. Hopefully it give you a better understanding of the syntax and the meaning behind inheritance.

Details

  1. The file dog.py contains a declaration for a Dog class. Save this file to your directory and study it. Notice what instance variables and methods are provided. The file also contains some code that runs the actual program. Make sure you understand what it does, and how.

  2. One use of inheritance is to change the behavior of specific methods. Create a a class called Pomeranian that extends Dog. Override the speak method of the Dog class by defining a method in the Pomeranian class with the same method signature. The method should print something typical of a Pomeranian.

    Modify the program to add statements to create an instance of the Pomeranian class and make it speak (do not remove Spot). Run the program. Both dogs should speak something different because both classes have different bodies for the speak method. Notice that you did not define the __init__ method for the Pomeranian class and yet you are still able to call it because it was inherited from the Dog class.

  3. In addition to replacing the behavior of a method in the parent class it is also possible to extend the behavior of a method in the parent class. Create a class called Labrador in the same file that also extends Dog. Add a second parameter to the __init__ method that specifies the color of the lab and store the lab's color in an attribute. Again override the speak method with something typical of a lab. Also include something about the lab's color in the speak print statement.

    Modify your program by adding statements to create a Labrador. Be sure to call the constructor method that specifies the name and the color. Also add a statement to make it speak. Run the program. The dog and Pomeranian should speak, but there should be an error with the lab. The name attribute is not defined because the Dog class's __init__ method was overridden in the Labrador class. To fix this add a call to the Dog class's __init__ method by using built-in method super by adding the following statement to the Labrador's __init__ method:

      super().__init__(name)
    

    Run the dog_test program to verify that the program now works.

Example

>>> spot = Dog("Spot")
>>> spot.speak()
Spot says Woof.
>>> bandit = Pomeranian("Bandit")
>>> bandit.speak()
Bandit says Squeak.
>>> spike = Labrador("Spike", "Blond")
Spike, the Blond Labrador says Bark.

Lab Assignment 9
Shapes

Inheritance also allows us to abstract the core components of a classification of objects, to make our code more general. For example, in Tkinter the same pieces of data really represent most of the things that can be drawn on the screen.

Today, you will make a class structure that will allow you to represent an arbitrary shape. You will then draw those shapes to a Tk canvas.

Details

Again, I would like you to start on paper. Have either myself or one of the lab assistants check your paper work before you get started coding. You should try the paper pseudo-code before you look at the hint. The hint is there if you are completely lost, however.

In a file called drawing_shapes.py, create a class called Shape. This class should have all the attributes necessary to draw a generic shape, as well as any methods that you can use to put the generic shapes onto a tk window. For now, this shape can be drawn as just a dot on the canvas.

You should have at least 3 shapes that inherit the generic Shape class: Circle, Square, and Triangle. You should use the currently defined methods in the Shape class when appropriate, and override methods when you need to.

Use these three shapes to create an interesting drawing on your Tk window.

Hint

  • At the very least, your Shape class needs an attribute for the canvas, as well as the location of the shape on the canvas. Depending on how creative you get, you might also want a fill color.

    You also need to be able to draw the shape, so you will at least need a method for that. For this generic shape, just draw a dot at the location stored in the Shape class.

  • Your other shapes need a slight modification to the Shape constructor. For example, Circle needs a radius for drawing, whereas Triangle and Square need a side length in order to draw. Override the constructor, but don't forget to call super's constructor as well!

    You will also need to override the draw method to handle drawing the new shapes.

 

Challenge

Right now, anyone with programming experience can probably draw using your program. However, that really limits the amount of users you can have with this setup. A better setup would allow users to click on the canvas to draw.

Add to the functionality to allow users to draw by clicking on the canvas. You will need some mechanism that allows users to select which shape they want to draw next. You can either bind keyboard listeners that select the shapes, or you can explore the Tk button widget to allow users to select a shape based on mouse clicks as well.

You may need to alter your classes slightly for this, since it will be hard to determine the size of the shapes to get drawn. Unless...

 

Challenge

If you implement a mouse motion listener properly, you can actually allow for a shape to get re-sized as they get drawn. You just have to make sure that you remove the previous shape that was drawn when you redraw the new shape.

This one behaves a little bit funny. You will have to register the mouse motion listener on a mouse press, and "unregister" the listener on mouse release. Take a look at the tkinter documentation to see how this works.

Again, this might require some slight modifications to your classes.


Submission

When you have finished, create a tar file of your lab9 directory. To create a tar file, execute the following commands:

cd ~/cs170/labs
tar czvf lab9.tgz lab9/

To submit your activity, go to inquire.roanoke.edu. You should see an available assignment called Lab Assignment 9. Make sure you include a header listing the authors of the file.


In-Class Notes