Notes on Object-Oriented Approaches
The fundamental reason for using design patterns is to keep classes separated and prevent them from having to know too much about one another. Equally important, using these patterns helps you avoid reinventing the wheel and enables you to describe your programming approach succinctly in terms other programmers can easily understand.
There are a number of strategies that OO programmers use to achieve this separation, among them encapsulation and inheritance. Nearly all languages that have OO capabilities support inheritance. A class that inherits from a parent class has access to all the methods of that parent class. It also has access to all its variables. However, by starting your inheritance hierarchy with a complete, working class, you might be unduly restricting yourself as well as carrying along specific method implementation baggage. Instead, Design Patterns suggests that you always
Program to an interface and not to an implementation.
Putting this more succinctly, you should define the top of any class hierarchy with an abstract class or an interface, which implements no methods but simply defines the methods that class will support. Then in all your derived classes, you have more freedom to implement these methods as best suits your purposes.
Python does not directly support interfaces, but it does let you write abstract classes, where the methods have no implementation. Remember the comd interface to the DButton class:
class DButton(Button): def __init__(self, master, **kwargs): super().__init__(master, **kwargs) super().config(command=self.comd) # abstract method to be called by children def comd(self): pass
This is a good example of an abstract class. Here you fill in the code for the command method in the derived button classes. As you will see, it is also an example of the Command design pattern.
The other major concept you should recognize is object composition. We have already seen this approach in the Statelist examples. Object composition is simply the construction of objects that contain others—the encapsulation of several objects inside another one. Many beginning OO programmers tend to use inheritance to solve every problem, but as you begin to write more elaborate programs, the merits of object composition become apparent. Your new object can have the interface that works best for what you want to accomplish without having all the methods of the parent classes. Thus, the second major precept suggested by Design Patterns is
Favor object composition over inheritance.
At first this seems contrary to the customs of OO programming, but you will see any number of cases among the design patterns where we find that inclusion of one or more objects inside another is the preferred method.