150 likes | 166 Views
This set of lecture notes discusses the mechanisms of inheritance and composition for software reuse. It explains the concept of substitutability and provides examples of building sets from lists using both approaches. The advantages of inheritance and composition are compared, and the concept of dynamic composition is introduced with an example.
E N D
CSci 556Multiparadigm Programming Mechanisms for Software ReuseFall Semester 2018Lecture Notes
Mechanisms for Software Reuse (Budd's UOOPJ, Ch. 10) This is a set of slides originally created to accompany chapter 10 of Timothy Budd's textbook Understanding Object-Oriented Programming with Java, Updated Edition (Addison-Wesley, 2000) Created: 14 Aug 2004; Revised 4 Mar 2010; 13 Feb 2018; 24 September 2018
Inheritance and Substitutability • Idealization of inheritance • Instance of "subclass" can substitute for instance of parent • Substitutability by implementing interfaces in Java as well as subclassing • Abstract concept captured with two rules of thumb • is-a relation • "A dog is-a mammal" sounds right • Natural for dog to inherit from mammal • has-a relation • "A car is-a(n) engine" sounds wrong • Not natural to use inheritance • But "a car has-a(n) engine" sounds right • Can use composition (aggregation) 1
Two Approaches to Software Reuse in OOP • Inheritance • is-a relationship • Useful when new software component has all behavior of existing component, plus more – extends • Inheritance of just specification or of code as well • Inheritance can be used if "new-thing is-a old-thing" sounds reasonable • Composition (aggregation) • has-a relationship • Useful when new software component builds on existing system but differs fundamentally from it • Composition can be used if "new-thinghas-a old-thing" sounds reasonable 2
Example Building Sets from Lists Suppose already have List data type with behavior class List { public List() { ... } public void add(int) { ... } public void remove(int) { ... } public boolean includes(int) { ... } public int firstElement() { ... } ... } Wish to build Set data type • Elements are unique and unordered in set 3
Using Inheritance class Set extends List { public void add(int) { ... } } • Only need specify what is new • add() method overrides the one in List • Everything else stays same as in List • Inherits unneeded firstElement() operation • Set potentially substitutable for List -- undesirable! 4
Using Composition (Aggregation) class Set { public Set() { ... data = new List(); ... } public void add(int) { ... } public void remove(int) { ... } public boolean includes(int) { return data.includes(int); } private List data; } • Note data field of type List • Redefine all operations except unneeded operation firstElement() • May use List operations on data field • Set not substitutable for List 5
Comparison of Inheritance and Composition • Advantages of inheritance over composition • Shorter code • Increased functionality (thru polymorphism) • Sometimes less execution overhead • Advantages of composition over inheritance • Easier to see and understand functionality • No "yo-yo" effect • Inappropriate operations on constituent ("parent") type hidden • Easier to change to different constituent type 6
Combining Inheritance and Composition Java API class InputStream • Abstract concept of an input stream • Concrete realizations differ by source of data values, each substitutable for parent • ByteArrayInputStream, FileInputStream, PipedInputStream, SequenceInputStream, StringBufferInputStream • Also filters (or wrappers) for input streams that specify processing of data, both inheriting from and having InputStream component • FilterInputStream • gets data from its componentInputStream of any type • but also substitutable for InputStream • Note two orthogonal sources of variation • Data source and processing 7
Dynamic Composition An advantage of composition over inheritance • Composition: binding time • Inheritance: compile time 8
Dynamic Composition Example class Frog { public Frog() { behavior = new TadpoleBehavior(); } public void grow() // see if behavior should change { if (behavior.growUp()) { behavior = new AdultFrogBehavor(); } behavior.grow(); // behavior does actual work behavior.swim(); } private FrogBehavior behavior; } 9
Dynamic Composition Example (cont.) abstract class FrogBehavior { public void grow(); public void swim(); public boolean growUp() { return false; } } class TadpoleBehavior extends FrogBehavior { public void grow() { ... } public void swim() { ... } public boolean growUp() { age++; return (age > 24); } private int age = 0; } class AdultFrogBehavior extends FrogBehavior { public void grow() { ... } public void swim() { ... } } 10
Dynamic Composition (cont.) • Frog delegates its work to FrogBehavior object • Polymorphic variable behavior holds current FrogBehavior object • Different FrogBehavior classes for differing behaviors (tadpole or adult) • Frog object modifies behavior component when change needed (from tadpole to adult at proper age) • Polymorphism means correct grow() and swim() methods called for current stage • Frog object (interface) unchanged throughout life, but actual behavior changed as needed 11
Will Widespread Software Reuse Become Reality? Even with the right mechanisms, software reuse not guaranteed to occur – Also need • Right culture • Solid reusable component libraries • Guidelines for producing reusable components • Appropriate training of programmers for reuse • Willingness of programmers to reuse • Willingness of managers to pay for development of reusable components • Patience and long-term dedication to reuse 12
Acknowledgement This work was supported by a grant from Acxiom Corporation titled “The Acxiom Laboratory for Software Architecture and Component Engineering (ALSACE).” 13