Chapter 11 - Replacement and Refinement
- Adding, Replacing, and Refining
- Until now assumed we only added methods to a child class
- Override one of the parents method in the child
- To override - must have same name as parents method
- Override to replace - totally replace the parents method with
the childs version - no code in the parent is ever executed -
no enforcement of substitutibility therefore no common interface
- Override to refine - as part of the childs code, the parents code
is executed - maintains substitutibility and interface
- Replacement
- Replace the parents method completely.
- Replacement and Principle of Substitutability
- No guarantee that child method will be related to parents
- Substitutability not enforced
- How could we enforce substitutability
- Ignore the problem (Smalltalk, C++, Java, etc.)
- Use assertions (Eiffel) that are inherited and enforced so
child method has to meet them
- Separate subclass concept from subtype concept. Don't allow
replacement in subtypes. (Java does this somewhat.)
- Don't allow any replacement semantics at all.
- Notating Replacement
- Most languages don't require any notation to show that a method
is either overriden or is overriding a method
- C++ requires the word virtual to be included on the methods to
be overriden in the parent class but nothing in the child
class - NOTE - the virtual only is needed if you want
the polymorphic (late binding) characteristics. Without virtual
the child class will still override the parent but you only get
the child's version using a child instances otherwise, the parents
version is executed. For completeness, usually the overriding
methods in the child are also marked virtual.
- If notation is in parent, then implementing the calls is easier
and more efficient - no possiblity of overriding with delayed
binding then you can implement methods as procedure calls
- Leaving off the marking is much more flexible
- Replacement in Various Languages
- Relacement in C++
- Intertwines the concepts of overriding, overloading, virtual (or
polymorphic) functions, and constructors.
- For overriding, the name and parameters MUST match exactly and
you include virtual in the parent class function prototype.
- Usually, the return type is also the same or at least a subclass
of the return type (ie. if parent returns something of type parent
then child can return something of type child or type parent)
- Non-virtual methods are always static - method is determined by
the static type of the receiver. Virtual methods are dynamic -
method is determined by the dynamic type of the receiver.
- A child constructor can refine a parents constuctor but doesn't
replace the parents constructor
- Refinement
- As part of the child's method, the parents method is executed.
- Guarantees substitutibility
- This need seen most often in initialization of the parent part of
the child
- You could "achieve" refinement by rewriting the parent code but
this is not a great idea. Just invoke the parent method.
- Refinement in Various Languages
- Use the scope operator (parent::show()) to invoke the parent code
- Use the : operator in a constructor (Child():Parent()) to
initialize the parent portion of the child class - or rely on the
default constructor (constuctor with no arguments) for the parent
class (poor idea) - same general idea for destructors