0% found this document useful (0 votes)
105 views9 pages

Mechanisms For Software Reuse

The document discusses mechanisms for software reuse through inheritance and composition. It covers inheritance vs composition, abstract classes vs interfaces, advantages and disadvantages of each, and how inheritance and composition can be combined. Specifically, it provides examples of how Java streams use inheritance and composition together to provide flexible implementations.

Uploaded by

eveswan2008
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
105 views9 pages

Mechanisms For Software Reuse

The document discusses mechanisms for software reuse through inheritance and composition. It covers inheritance vs composition, abstract classes vs interfaces, advantages and disadvantages of each, and how inheritance and composition can be combined. Specifically, it provides examples of how Java streams use inheritance and composition together to provide flexible implementations.

Uploaded by

eveswan2008
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 9

1

14. Mechanisms for Software Reuse

5/5/18

John Roberts

2
Overview
• Inheritance vs. Composition,

Part 1

• Abstract classes vs. 



Interfaces

• Inheritance vs. Composition,



Part 2

• Advantages and
Disadvantages

• Combining Composition and


Inheritance

3
Inheritance vs. Composition (Aggregation) Part 1

• is-a vs. has-a

• Car is-a Vehicle (inheritance)

• Case has-a Engine (composition)

• Will the is-a relationship be constant throughout the


lifetime of the application?
4
Inheritance vs. Composition (Aggregation) Part 1

• Initially, Employee is-a Person

• But, Employee might be a role played by a Person at certain points


in time

• What if the Person becomes unemployed?

• What if the Person is both an Employee and a Supervisor?

• Normally, we use Composition to model these relationships



class Person {

Role workingRole;

// …

}

5
Overview
• Inheritance vs. Composition,

Part 1

• Abstract classes vs.


Interfaces

• Inheritance vs. Composition,



Part 2

• Advantages and
Disadvantages

• Combining Composition and


Inheritance

6
Abstract classes vs. Interfaces

• Abstract classes are used when you want to share the


structure or code among super- and sub-classes

• Interfaces are used when you want to share the


specification of behavior but no code
7 Note code applicable to all sub classes; we’ll need this same operation
Example

public abstract class AST {


// …
protected ArrayList<AST> kids;

public AST getKid( int i ) {


if ( (i <= 0) || (i > kidCount())) {
return null;
}

return kids.get(i - 1);


}
}

8 Note implementation details may change, but behavior is consistent


Example

public interface java.util.Enumeration {


public abstract boolean hasMoreElements();
public abstract Object nextElement();
}

9
Overview
• Inheritance vs. Composition,

Part 1

• Abstract classes vs. 



Interfaces

• Inheritance vs. Composition,



Part 2

• Advantages and
Disadvantages

• Combining Composition and


Inheritance
10
Inheritance vs. Composition (Aggregation) Part 2

• Consider two different possible implementations of a


Stack in Java
class Stack extends Vector { class Stack {
public Object push( Object item ) { private Vector theData;
addElement( item );
return item; public Stack() {
} theData = new Vector();
public Object peek() { }
return elementAt( size() - 1 );
} public boolean isEmpty() {
} return theData.isEmpty();
}
}

11
Inheritance vs. Composition (Aggregation) Part 2
class Stack extends Vector {
public Object push( Object item ) { • Stacks can use protected
addElement( item );
members of Vector
return item;
}
public Object peek() { • Stacks can be used wherever
return elementAt( size() - 1 );
Vectors are required as
}
} arguments

• Reuse Vector methods such as


size, isEmpty

• Reuse methods that might not


make sense for Stacks (we can
remove any item in a Vevtor)

12
Inheritance vs. Composition (Aggregation) Part 2
class Stack {
• We can change the private Vector theData;
implementation of Stack from
public Stack() {
Vectors to e.g. array, without theData = new Vector();
any impact on code that uses }
Stacks
public boolean isEmpty() {
return theData.isEmpty();
• Surface area is smaller (don’t }
need to understand Vectors in }
order to understand Stacks)

• Meaningless behavior isn’t


exposed (extending Vector
allows us to do things to Stacks
like insertElementAt()
13
Overview
• Inheritance vs. Composition,

Part 1

• Abstract classes vs. 



Interfaces

• Inheritance vs. Composition,



Part 2

• Advantages and
Disadvantages

• Combining Composition and


Inheritance

14
Inheritance Advantages

• Substitutability

• Shorter implementation times due to code reuse

• Field/method access - Can access public and protected


members of the super class

• Polymorphism is available

15
Inheritance Disadvantages

• Tight coupling of subclass with superclass

• Changes to superclass have rippling effect on all


subclasses

• Users of a class with inheritance must look at the class


and all superclasses to understand behavior - large
surface area

• Might use methods in superclass that are not really


appropriate
16
Composition Advantages

• Easier to understand operations that are available (i.e. not


exposing inherited behaviors like we saw with Stack
extends Vector’s insertElementAt() )

• Changes to private data have no effect on users of class

17
Composition Disadvantages

• Field/method access - Can only access public members


of the composed class

• No polymorphism

18
Overview
• Inheritance vs. Composition,

Part 1

• Abstract classes vs. 



Interfaces

• Inheritance vs. Composition,



Part 2

• Advantages and
Disadvantages

• Combining Composition and


Inheritance
19
Combining Composition and Inheritance

• Very powerful

• Can be used to greatly simplify the inheritance hierarchy

20
Example: Java Stream Wrappers

• InputStream

• ByteArrayInputStream

• FileInputStream

• PipedInputStream

• FilterInputStream

• BufferedInputStream

• DataInputStream

21
Example: Java Stream Wrappers

• Subclassing allows processing an InputStream regardless


of where the bytes come from

class FilterInputStream extends InputStream {


// source of bytes is from any InputStream

protected InputStream in;

FilterInputStream( InputStream in ) { 

this.in = in;
}

// etc.

} 

22
Example: Java Stream Wrappers

• FilterInputStreams can be used wherever we expect an


InputStream since it subclasses InputStream

• It gets the bytes from in and then performs filtering

• In this case, we are provided with orthogonal sources of


variation - the source of bytes, and added functionality (e.g.
filtering, buffering)

• We are avoiding an explosion of the inheritance


hierarchy

• What if we don’t use composition with inheritance?

23
Example: Java Stream Wrappers

• Hierarchy grows exponentially

• InputStream

• FilterInputStream

• BufferedInputStream

• BufferedDataInputStream

• // A lot more

• DataInputStream

• // etc.

24 Leveraging implementation of shared code, adding new behavior


Example: BufferedReader

• http://developer.classpath.org/doc/java/io/BufferedReader-source.html

• 63: Reader in;



composition adds buffering services to the Reader it is wrapping

• 64: char[] buffer;



the buffered characters read from in

• 117: // new constructor

• 102: // use new constructor (with


DEFAULT_BUFFER_SIZE)

• 429: // readLine method added


25 Composition
Dynamic Composition

• Combining composition and inheritance to change the


behavior of a program as it is running (dynamically)
class Frog {

private FrogBehavior behavior;

public Frog() {

behavior = new TadpoleBehavior();
}

public grow() {
// see if behavior should change
if (behavior.growUp()) {
behavior = new AdultFrogBehavior();
}

behavior.grow(); // behavior does actual work


behavior.swim();
}
}

26 Inheritance
Dynamic Composition

• Combining composition and inheritance to change the


behavior of a program as it is running (dynamically)
abstract class FrogBehavior {

public boolean growUp() { return false; }
public abstract void grow();

public abstract swim();
}

class TadpoleBehavior extends FrogBehavior {


private int age = 0;
public boolean growUp() {
return (++age > 24)? true : false;
}
public void grow() {...}

public void swim() {...}
}

class AdultFrogBehavior extends FrogBehavior {


public void grow() {...}

public void swim() {...}
}

You might also like