Putting an Object in a Safe State, Page 6
Some of the most basic operations in programming become more complicated when you're dealing with complex data structures and objects. For example, when you want to copy primitive data types, the process is quite straightforward. However, copying objects is not quite as simple. In his book Effective C++, on page 34, Scott Meyers devotes an entire section to copying and assigning objects.
Classes and References
The problem with complex data structures and objects is that they may contain references. Simply making a copy of the pointer does not copy the data structures or object that it references.
The problems arise when comparisons and copies are performed on objects. Specifically, the question boils down to whether or not you follow the pointers or not. For example, there should be a way to copy an object. Again, this is not as simple as it may seem. Since objects may contain references, these reference trees must be followed to do a valid copy (if you truly want to do a deep copy).
Deep Versus Shallow Copies
A deep copy is when all the references are followed and new copies are created for all referenced objects. There may be many levels involved in a deep copy. For objects with references to many objects, which in turn may have references to even more objects, the copy itself can create significant overhead. A shallow copy would simply copy the reference and not follow the levels. Gilbert and McCarty have a good discussion about what shallow and deep hierarchies are on page 265 of Object-Oriented Design in Java in a section called "Prefer a Tree to a Forest."
To illustrate, in Figure 8, if you just do a simple copy of the object (called a bitwise copy), then any object that the primary object references will not be copied—only the references will be copied. Thus, both objects (the original and the copy) will point to the same objects. To perform a complete copy, in which all reference objects are copied, you have to write the code to create all the sub-objects.
Figure 8: Following object references.
This problem also manifests itself when comparing objects. As in the copy function, this is not as simple as it may seem. Because objects contain references, these reference trees must be followed to do a valid comparison of objects. In most cases, languages provide a default mechanism to compare objects. As is usually the case, do not count on the default mechanism. When designing a class, you should consider providing a comparison function in your class that you know will behave, as you want it to.
This article covers a number of advanced O-O concepts that, although perhaps not vital to a general understanding of O-O concepts, are quite necessary in the higher-level O-O tasks such as designing a class and putting an object in a safe-state.
Gilbert, Stephen, and Bill McCarty: Object-Oriented Design in Java. The Waite Group, 1998.
Tyma, Paul, Gabriel Torok and Troy Downing: Java Primer Plus. The Waite Group, 1996.
Meyers, Scott: Effective C++. Addison-Wesley, 1992.
About the Author
Matt Weisfeld is a faculty member at Cuyahoga Community College (Tri-C) in Cleveland, Ohio. Matt is a member of the Information Technology department, teaching programming languages such as C++, Java, and C# .NET as well as various web technologies. Prior to joining Tri-C, Matt spent 20 years in the information technology industry gaining experience in software development, project management, business development, corporate training, and part-time teaching. Matt holds an MS in computer science and an MBA in project management. Besides the first edition of The Object-Oriented Thought Process, Matt has published two other computer books, and more than a dozen articles in magazines and journals such as Dr. Dobb's Journal, The C/C++ Users Journal, Software Development Magazine, Java Report, and the international journal Project Management. Matt has presented at conferences throughout the United States and Canada.