Online Book Reader

Home Category

Learning Python - Mark Lutz [340]

By Root 1598 0
functions. The participation of methods in class inheritance, though, allows us to naturally customize existing software by coding subclasses with new method definitions, rather than changing existing code in-place. There is really no such concept with modules and functions.

As an example, suppose you’re assigned the task of implementing an employee database application. As a Python OOP programmer, you might begin by coding a general superclass that defines default behavior common to all the kinds of employees in your organization:

class Employee: # General superclass

def computeSalary(self): ... # Common or default behavior

def giveRaise(self): ...

def promote(self): ...

def retire(self): ...

Once you’ve coded this general behavior, you can specialize it for each specific kind of employee to reflect how the various types differ from the norm. That is, you can code subclasses that customize just the bits of behavior that differ per employee type; the rest of the employee types’ behavior will be inherited from the more general class. For example, if engineers have a unique salary computation rule (i.e., not hours times rate), you can replace just that one method in a subclass:

class Engineer(Employee): # Specialized subclass

def computeSalary(self): ... # Something custom here

Because the computeSalary version here appears lower in the class tree, it will replace (override) the general version in Employee. You then create instances of the kinds of employee classes that the real employees belong to, to get the correct behavior:

bob = Employee() # Default behavior

mel = Engineer() # Custom salary calculator

Notice that you can make instances of any class in a tree, not just the ones at the bottom—the class you make an instance from determines the level at which the attribute search will begin. Ultimately, these two instance objects might wind up embedded in a larger container object (e.g., a list, or an instance of another class) that represents a department or company using the composition idea mentioned at the start of this chapter.

When you later ask for these employees’ salaries, they will be computed according to the classes from which the objects were made, due to the principles of the inheritance search:[59]

company = [bob, mel] # A composite object

for emp in company:

print(emp.computeSalary()) # Run this object's version

This is yet another instance of the idea of polymorphism introduced in Chapter 4 and revisited in Chapter 16. Recall that polymorphism means that the meaning of an operation depends on the object being operated on. Here, the method computeSalary is located by inheritance search in each object before it is called. In other applications, polymorphism might also be used to hide (i.e., encapsulate) interface differences. For example, a program that processes data streams might be coded to expect objects with input and output methods, without caring what those methods actually do:

def processor(reader, converter, writer):

while 1:

data = reader.read()

if not data: break

data = converter(data)

writer.write(data)

By passing in instances of subclasses that specialize the required read and write method interfaces for various data sources, we can reuse the processor function for any data source we need to use, both now and in the future:

class Reader:

def read(self): ... # Default behavior and tools

def other(self): ...

class FileReader(Reader):

def read(self): ... # Read from a local file

class SocketReader(Reader):

def read(self): ... # Read from a network socket

...

processor(FileReader(...), Converter, FileWriter(...))

processor(SocketReader(...), Converter, TapeWriter(...))

processor(FtpReader(...), Converter, XmlWriter(...))

Moreover, because the internal implementations of those read and write methods have been factored into single locations, they can be changed without impacting code such as this that uses them. In fact, the processor function might itself be a class to allow the conversion logic of converter to be filled in by inheritance, and to allow

Return Main Page Previous Page Next Page

®Online Book Reader