已读64%
预计阅读本页时间:-
预计阅读本页时间:-
Test Your Knowledge: Answers
- In the final version of our classes, Manager ultimately inherits its __str__ printing method from AttrDisplay in the separate classtools module. Manager doesn’t have one itself, so the inheritance search climbs to its Person superclass; because there is no __str__ there either, the search climbs higher and finds it in AttrDisplay. The class names listed in parentheses in a class statement’s header line provide the links to higher superclasses.
- Shelves (really, the pickle module they use) automatically relink an instance to the class it was created from when that instance is later loaded back into memory. Python reimports the class from its module internally, creates an instance with its stored attributes, and sets the instance’s __class__ link to point to its original class. This way, loaded instances automatically obtain all their original methods (like lastName, giveRaise, and __str__), even if we have not imported the instance’s class into our scope.
- It’s important to move processing into methods so that there is only one copy to change in the future, and so that the methods can be run on any instance. This is Python’s notion of encapsulation—wrapping up logic behind interfaces, to better support future code maintenance. If you don’t do so, you create code redundancy that can multiply your work effort as the code evolves in the future.
- Customizing with subclasses reduces development effort. In OOP, we code by customizing what has already been done, rather than copying or changing existing code. This is the real “big idea” in OOP—because we can easily extend our prior work by coding new subclasses, we can leverage what we’ve already done. This is much better than either starting from scratch each time, or introducing multiple redundant copies of code that may all have to be updated in the future.
- Copying and modifying code doubles your potential work effort in the future, regardless of the context. If a subclass needs to perform default actions coded in a superclass method, it’s much better to call back to the original through the superclass’s name than to copy its code. This also holds true for superclass constructors. Again, copying code creates redundancy, which is a major issue as code evolves.
- Generic tools can avoid hardcoded solutions that must be kept in sync with the rest of the class as it evolves over time. A generic __str__ print method, for example, need not be updated each time a new attribute is added to instances in an __init__ constructor. In addition, a generic print method inherited by all classes only appears, and need only be modified, in one place—changes in the generic version are picked up by all classes that inherit from the generic class. Again, eliminating code redundancy cuts future development effort; that’s one of the primary assets classes bring to the table.
- Inheritance is best at coding extensions based on direct customization (like our Manager specialization of Person). Composition is well suited to scenarios where multiple objects are aggregated into a whole and directed by a controller layer class. Inheritance passes calls up to reuse, and composition passes down to delegate. Inheritance and composition are not mutually exclusive; often, the objects embedded in a controller are themselves customizations based upon inheritance.
- The classes in this chapter could be used as boilerplate “template” code to implement a variety of types of databases. Essentially, you can repurpose them by modifying the constructors to record different attributes and providing whatever methods are appropriate for the target application. For instance, you might use attributes such as name, address, birthday, phone, email, and so on for a contacts database, and methods appropriate for this purpose. A method named sendmail, for example, might use Python’s standard library smptlib module to send an email to one of the contacts automatically when called (see Python’s manuals or application-level books for more details on such tools). The AttrDisplay tool we wrote here could be used verbatim to print your objects, because it is intentionally generic. Most of the shelve database code here can be used to store your objects, too, with minor changes.