7.8 Summary
In this chapter, we covered the following:
A class can represent characteristics and behavior in common across other classes. For example, the
<directed-angle>class represents the degrees-minutes-seconds aspects that are common to latitude and longitude. Also, the<sixty-unit>class represents thetotal-secondsthat are common to<time>and<angle>.Classes can be used to represent differences between two similar kinds of objects. For example, the
<latitude>and<longitude>classes are similar in that both classes inherit from<directed-angle>, and neither class defines additional slots. However, by providing the two classes,<latitude>and<longitude>, we make it possible to identify objects as being of type<latitude>or<longitude>, and we make it possible to customize the behavior of operations on<latitude>and<longitude>as needed.In many object-oriented libraries and programs, certain classes are not intended to have direct instances. You can define those classes as abstract classes to document their purpose.
When you have two related classes and both will have direct instances, it is good practice to define a third class to be the superclass of the two other classes. The superclass is abstract, and the other two classes are concrete. We used this style in the time classes, the angle classes, and the position classes. People can use the abstract superclasses, such as
<position>, as the type of objects that can be any kind of position.In proper modularity, a method on a particular class should not depend on information that is private to second class. If someone changes the representation of the second class, the method could break. We showed an example of breaking this rule when one version of the
saymethod on<absolute-position>printed "latitude" and "longitude" after callingsayon the directed angles stored in its two slots. The method on<absolute-position>acted on the knowledge that the method on<directed-angle>does not print "latitude" or "longitude."
One of the challenges of modular design is for you to decide which attributes to generalize (by moving them up to higher, or more general, classes in the inheritance graph), and which attributes to specialize (by moving them down the inheritance graph into more specific classes). Another challenge is deciding when to split a class into multiple behaviors, and when to introduce more abstract classes to hold shared behavior. No computer language can make these decisions for you, but dynamic languages typically allow more freedom to explore these relationships. Generic functions and multimethods allow more freedom in defining behavior than does attaching a method to a single class.




