Reference semantics vs. value semantics
- Value semantics: variables directly contain values.
- Reference semantics: variables contain addresses that refer (point) to objects.
Equality vs. identity
- Equality: are two (possibly) different objects equivalent?
- Identity: do two references refer to the same objects?
- How are equality and identity related?
Inheriting from java.lang.Object
Implementing classes are usually required to provide the following methods:
- clone (if the objects are mutable and cloning is required)
- compareTo (if a default ordering is required)
- Mechanism for grouping related or collaborating classes (cf. default package-level member access).
- Implemented as mapping from fully qualified class names to file system.
- default (package)
Subtyping vs. subclassing/inheritance
- Subtyping allows substituting a more specific object for a more general one.
- Inheritance is a mechanism for a subclass to reuse code from a superclass.
- Inheritance usually enables subtyping. But it is not the only way to enable subtyping; implementing or extending an interface are other ways.
Static vs. dynamic type
- Static type: declared type of a variable.
- Dynamic type: actual type of the object to which the variable refers.
- How are static and dynamic type of a variable related?
- Casting: treat an object as if it had a different static type. Three different situations: downcast, upcast, crosscast.
- Concrete class: can be instantiated. All specified methods are fully implemented.
- Abstract class: cannot be instantiated. Some or all of the specified methods are not implemented.
- Interface: limit case of a fully abstract class for specification purposes only. None of the specified methods are implemented, and there are no instance variables (only class-level constants).
Relationships between classes
- is-a: subtyping
- has-a: aggregation, composition
- uses-a: dependency
Clone in the context of the Composite pattern
In general, cloning allows you to make a copy of an object. The clone method in Java is similar to the copy constructor in C++, but it is an ordinary method, unlike the copy constructor. Once you have the original object and its clone, then you can modify each one independently.
Cloning models the real-life situation where you build a prototype of something, say a car or a piece of furniture, and once you like it, you clone it as many times as you want. These things are composites, and the need to be cloned deeply (recursively).
As another example, imagine a parking garage with a list of cars that have access to it. To build another garage to handle the growing demand, you can clone the garage and the access list. But the cars should not get cloned. That's because the garage is not composed of the cars.
As we can see, the conceptual distinction between aggregation and composition has significant consequences for the implementation of the relationship. True, both relationships are represented as references in Java. However, composites usually require a deep clone (if cloning is supported): each parent is responsible for cloning its children.
Note also that you don't need to clone at all if your objects are not mutable because you wouldn't be able to distinguish the original from the clone anyway.