Understanding Replacement and Refinement in Object-Oriented Programming
This document explores the concepts of replacement and refinement within object-oriented programming (OOP), particularly in Java and other languages. It outlines the two primary models: Replacement, where child methods replace parent methods, and Refinement, where the child and parent behaviors are merged. It emphasizes the implications of these models on code behavior, maintenance, and documentation requirements across different programming languages. The notes are based on lecture materials designed for engineering courses, providing a comprehensive overview for students and professionals in software architecture.
Understanding Replacement and Refinement in Object-Oriented Programming
E N D
Presentation Transcript
Engr 691Special Topics in Engineering ScienceSoftware ArchitectureSpring Semester 2004Lecture Notes
Replacement and Refinement This Web document was based on a set of slides created by the instructor for use in the Fall 1997 and Spring 1999 offerings of the object-oriented design and programming course. That set was, in turn, based on a set of slides created by Timothy Budd to supplement chapter 11 of his textbook An Introduction to Object-Oriented Programming, Second Edition (Addison-Wesley, 1997)
Replacement and Refinement What happens when child classes have methods with the same names as parent? There are two general models describing this situation: Replacement: • "American" school of OOP – child method replaces parent method Refinement: • "Scandinavian" school of OOP – behavior of parent and child classes are merged to form new behavior • If replacement used, then some mechanism usually provided for refinement • If refinement default, then replacement not possible
Preserving is-a • Replacement makes preserving principle of substitutability difficult • No guarantee that child class will do anything similar to the parent • Other methods that depend upon behavior from parent class may fail • Great havoc can ensue if programmer is not careful
Documenting Replacement or Refinement • Some languages require parent class to indicate replacement is permitted (e.g., virtual in C++) • Some languages require child class to indicate replacement (e.g., override in Object Pascal) • Some languages do not automatically document replacement or refinement (e.g., Java, Smalltalk)
Replacement in Java • Constructors use refinement • By default, all other methods can be overridden and replaced • No keyword to denote overriding (as with virtual in C++ or override in Object Pascal) • Binding of "message" (call) to method done based on dynamic type of receiver object • Can even replace data fields, although these are static and not dynamic • Keyword final on method prohibits replacement • Keyword final on class prohibits subclassing altogether
Refinement • Method in parent and method in child merged to form new behavior • Parent class method always executed • Users guaranteed at least behavior of parent • Performed automatically in some languages (e.g., Simula, Beta) • Performed by directly invoking parent method from within child method in other languages (e.g., Java, C++)
Refinement in Simula and Beta • Execute code from parent first -- when INNER statement encountered, execute child code • Parent classes wrap around child -- almost reverse of American school languages • Guarantees functionality provided by parent classes
Refinement in Java • Default constructor of superclass called implicitly as first action by subclass constructor • Subclass constructor may explicitly call specific superclass constructor as super(...) in first statement • Subclass method may explicitly call overridden superclass method using classname super anywhere
Refinement in Java (continued) public class CardPile { public CardPile (int xl, int yl) { x = xl; y = yl; thePile = new Stack(); } public void addCard (Card aCard) { thePile.push(aCard); } ... }
Refinement in Java (continued) class DiscardPile extends CardPile { public DiscardPile (int x, int y) { super (x, y); } public void addCard (Card aCard) { if (! aCard.faceUp()) aCard.flip(); super.addCard(aCard); } ... }