19.1 Why Use Classes?
Remember when we told you that programs do things with stuff? In
simple terms, classes are just a way to define new sorts of stuff,
which reflect real objects in your program's domain.
For instance, suppose we've decided to implement
that hypothetical pizza-making robot we used as an example in Chapter 12. If we implement it
using classes, we can model more of its
real-world structure and relationships:
- Inheritance
-
Pizza-making robots are a kind of robot, and so possess the usual
robot-y properties. In OOP terms, we say they inherit properties from
the general category of all robots. These common properties need to
be implemented only once for the general case and reused by all types
of robots we may build in the future.
- Composition
-
Pizza-making robots are really collections of components that work
together as a team. For instance, for our robot to be successful, it
might need arms to roll dough, motors to maneuver to the oven, and so
on. In OOP parlance, our robot is an example of composition; it
contains other objects it activates to do its bidding. Each component
might be coded as a class, which defines its own behavior and
relationships.
General OOP ideas like inheritance and composition apply to any
application that can be decomposed into a set of objects. For
example, in typical GUI systems, interfaces are written as
collections of widgets—buttons, labels, and so on—which
are all drawn when their container is drawn
(composition). Moreover, we may be able to write
our own custom widgets—buttons with unique fonts, labels with
new color schemes, and the like—which are specialized versions
of more general interface devices (inheritance).
From a more concrete programming perspective, classes are a Python
program unit, just like functions and modules. They are another
compartment for packaging logic and data. In fact, classes also
define a new namespace much like modules. But compared to other
program units we've already seen, classes have three
critical distinctions that make them more useful when it comes to
building new objects:
- Multiple instances
-
Classes are
roughly factories for generating one or more objects. Every time we
call a class, we generate a new object, with a distinct namespace.
Each object generated from a class has access to the
class's attributes and gets a namespace of its own
for data that varies per object.
- Customization via inheritance
-
Classes also support the OOP notion of inheritance; they are extended
by redefining their attributes outside the class itself. More
generally, classes can build up namespace hierarchies, which define
names to be used by objects created from classes in the hierarchy.
- Operator overloading
-
By providing special protocol methods, classes can define objects
that respond to the sorts of operations we saw work on built-in
types. For instance, objects made with classes can be sliced,
concatenated, indexed, and so on. Python provides hooks classes can
use to intercept and implement any built-in type operation.
|