Introduction to Programming Week 8
This week we focused on a very popular and very powerful paradigm called object-oriented programming.
As you might guess from the name, in object-oriented programming everything is an object. Each type of object is called a class, and an object of a particular class is also called an instance of that class.
Part 1: Radios
Classes are defined by the data associated with them, and the things they can do. For example, a Radio class might want to keep track of what station it's tuned to and whether or not it's on. It would also have functions for the things we usually do with a radio - listening and changing settings maybe.
Because object-oriented programmers like to make up new words for things, data associated with a class are called attributes, and functions associated with a class are called methods.
We could make these variables and functions ourselves, but it's much easier to put them in a dedicated Radio class. That way all the functionality of the radio is encapsulated in the class, so if we want to reuse it later everything we need is built-in to the class. Additionally, classes allow for information hiding - just like we don't need to know what frequency modulation is or how antennas work to use a real radio, we don't need to know or remember exactly how the Radio class was built to know how to use it.
Part 2: Building a Radio Class
So how do we make our own classes? Python has some pretty predictable special syntax. If we wanted to write a Radio class we would first type:
Note that Radio is capitalized - while Python doesn't care, most programmers write functions and variables with lowercase names, but capitalize class names to distinguish them.
As with functions, it's a good idea to write a docstring next:
"""Represents a simple FM radio. A radio is either on or off, represented by a boolean. It is tuned to a particular station, represented by a float."""
After that we write the methods we want to include in the class, indented to indicate to Python that they're part of Radio.
The first method we usually write is called the constructor. This is a special method that's called to create an instance of the class. It's always named __init__ (short for initialize). The double underscores on either side indicate that it's a function that will be called in a special way (something other than the standard object.method() form we're used to).
The first parameter to __init__ and every other method is a special variable called self, which refers to the current instance of the class. When we call the methods elsewhere in our programs we don't explicitly add self as a parameter, Python does it for us.
To add data to the radio class, we can create instance variables as part of self, that are different for each instance of the class (i.e. two radios can be tuned to different stations, etc. simultaneously, rather than then sharing a single setting). Prefacing the variable name with two underscores indicates to Python that the variable is private, which unless you have a reason to not do is usually a good idea.
Finally, the complete constructor:
def __init__(self, station, on): """Constructs a Radio. station is the current station, on is whether or not the radio is currently on""" self.__myStation = station self.__isOn = on
Constructors don't need to return anything.
Then to create a new radio elsewhere in our program we'd only need to type
myRadio = Radio(88.1, True)
Two common types of methods are called accessors (or getters) and mutators (or setters). So that their purpose is immediately clear, getters usually have names starting with 'get', and setters usually have names starting with 'set'. For example, the following methods allow a user to learn or change the station our Radio is tuned to:
def getStation(self): return self.__myStation def setStation(self, newStation): self.__myStation = newStation.
Then we could call the functions as follows:
curStation = myRadio.getStation() myRadio.setStation(curStation+.2) # tune to the next channel
Of course, we can write whatever methods we want, and it's usually also be a good idea to write class-specific methods (maybe Radio.listen(), for example), and some other standard methods (like __str__). See the page on classes for details.