Upload
adair-dingle
View
85
Download
0
Tags:
Embed Size (px)
Citation preview
Copyright@2014 Taylor & Francis Adair Dingle All Rights Reserved
Object-‐Oriented Design
Inheritance vs.
Composi2on: Part I
Inheritance for Subtyping: Structural Reuse
Design Ques2ons
• How to streamline class design for reuse?
• What is the importance of type?
• How to dis2nguish between reuse mo2ves? – Composi2on? – Inheritance?
Copyright@2015 Adair Dingle
Key Observa2ons
• Inheritance and composi2on BOTH provide reuse
• Type dependencies are established by design
• Differing needs for flexibility may drive design
Copyright@2015 Adair Dingle
Chapter 6: Structural Design
Class Rela2onships = = Design alterna,ves for class use and reuse
• Composi2on • Containment • Inheritance • Code Reuse • Design Principles
Copyright@2014 Taylor & Francis Adair Dingle All Rights Reserved
Rela2onships • Containment aka Holds-‐A
– subObjects held, as in a container – LiSle or no type dependency
• Composi2on aka Has-‐A – subObjects part of class/type composi2on – Essen2al component => some (internal) type dependency
• Inheritance aka Is-‐a – Class hierachy: Base (parent) and Derived (child) classes
• subtype alters or augments inherited behavior
– significant (external) type dependency – Built-‐in (sub)type checking
Copyright@2014 Taylor & Francis Adair Dingle All Rights Reserved
Structural Design Details • Cardinality: How many subObjects?
– 1:1 for inheritance; 1-‐many for composi2on by design – Variable for containment
• Ownership – Child owns parent component: may NOT be released – Composing object may stub out/replace subObject – None, usually, for containment
• Life2me – 1:1 for inheritance; variable by design for composi2on
• Associa2on – Permanent for inheritance – Possibly transient for composi2on – Temporary for containment
Copyright@2014 Taylor & Francis Adair Dingle All Rights Reserved
Table 6.1 Rela2onship details: class to subordinate
Relationship Association Cardinality Ownership Dependency Replacement
Composition Stable Variable Transferable Yes Yes
Containment Temporary Variable No No Not relevant
Inheritance Permanent Fixed: 1-1 Implied Yes No
Copyright@2014 Taylor & Francis Adair Dingle All Rights Reserved
Rela2onships: Design Details • Different designs yield different
– control and maintainability
• Cardinality, ownership, life2me and associa2on – Indicate flexibility, stability, and/or extensibility
• Overhead gauged by these measures. • For example:
– has-‐a rela2onship may provide varying cardinality – is-‐a rela2onship cannot vary cardinality – has-‐a may postpone subObject instan2a2on – is-‐a cannot postpone parent instan2a2on
Copyright@2014 Taylor & Francis Adair Dingle All Rights Reserved
Example 6.1 Postponed Instan2a2on of SubObject
class justInTime { // need appropriate memory management details
// Suppress or define: copy constructor and operator= bigData* generator; …
public:
justInTime() { generator = 0; } … void process() { if ( !generator ) generator = new bigData; generator.process(); } …
};
Copyright@2014 Taylor & Francis Adair Dingle All Rights Reserved
Table 6.2 Design Effects of OO Rela2onships
Relationship Internal Access
External Access
Overhead (SubObject) Interface
Control
Has-A Public None Variable Avoidable
Suppressed May echo
Replacement Defer instantiation
Holds-A Public None Minimal Not relevant None
Is-a Public Protected
Public Unavoidable Support Extend Suppress
None
Copyright@2014 Taylor & Francis Adair Dingle All Rights Reserved
Rela2onships: Type Dependency
• Implicit in inheritance hierarchies – Expecta2on: subtypes (descendants) may override inherited behavior to customize, augment, or vary base behavior.
– Polymorphism and use of heterogeneous collec2ons is common in designs employing type dependencies
• Significant in has-‐a rela2onship
– Client remains isolated from internal dependencies.
Copyright@2014 Taylor & Francis Adair Dingle All Rights Reserved
Table 6.3 Object to SubObject Details
Accessibility Association Cardinality Ownership
Private
Temporary or Permanent
Fixed by class design same for all objects
Object External
Echoed functionality
Delayed instantiation
Fixed at instantiation Stable for object lifetime
Shared
Full or Partial access
Stable but Replaceable
Variable within object lifetime
Transferable
Copyright@2014 Taylor & Francis Adair Dingle All Rights Reserved
Has-‐A vs. Holds-‐a
• Has-‐a rela2onships imply type dependency – class dependent on subObject for data and/or func2onality – Constructor may instan2ate subObject – Class methods may be defined to replace/reset subObject
• Holds-‐a rela2onships imply temporary associa2on – No significant dependency on type held
• Type could be replaced • Number of subObjects held could be zero, without impact
– Type independence, like that of a container, expected
Copyright@2014 Taylor & Francis Adair Dingle All Rights Reserved
Has-‐A vs. Is-‐a
• Has-‐a allows one to encapsulate and control subObjects – design variability in cardinality, associa2on, life2me and ownership – Interfaces may, but need not, be echoed.
• Is-‐a implies a strong type dependency – Child object may stand in for parent object – Polymorphism, and heterogeneous collec2ons, supported through
inheritance and difficult to implement otherwise (see chapter 7)
• Is-‐a impera2ve to reuse func2onality – common interface – Extensibility promoted – Overhead is fixed as is cardinality, ownership, life2me and associa2on...
Copyright@2014 Taylor & Francis Adair Dingle All Rights Reserved
Example 6.4 Inheritance in C#=> Child stands in for Parent
Parent pObj;
// Substitutability: // parent object (reference) can hold address of child object
// Not symmetric: child reference cannot hold parent address
// pObj: handle of type Parent => // Parent interface accessible; child interface not
pObj = new Parent(); pObj.parentFn();
pObj = new Child1(); pObj.parentFn();
pObj = new Child2(); pObj.parentFn();
Copyright@2014 Taylor & Francis Adair Dingle All Rights Reserved
Inheritance : Language Differences
• Java and C# support only public inheritance – do not allow direct suppression of inherited interface
• C++ offers public, protected and private inheritance – only public inheritance typically used – with protected inheritance, all inherited public func2onality is demoted
to protected accessibility – with private inheritance, all inherited public and protected func2onality
is demoted to private accessibility => applica2on programmer has less accessibility via a derived object
• C++ allows class designers – to directly suppress inherited func2onality – to change accessibility of individual inherited class methods
Copyright@2014 Taylor & Francis Adair Dingle All Rights Reserved
Example 6.5 C++ Direct suppression of Inherited Func2onality
class Child: public Parent { … // fields private by default
void parentFn() { // now private => suppressed }
public:
…
};
…
Parent pObj;
Child cObj;
pObj.parentFn();
cObj.parentFn(); // compilation error: not accessible
Copyright@2014 Taylor & Francis Adair Dingle All Rights Reserved
Example 6.6 C# Designated suppression of Inherited Func2onality
public class Child: Parent { …
public void parentFn() { //NOP }
…
}
// application code
Parent pObj = new Parent();
Child cObj = new Child();
pObj.parentFn(); // parent functionality
cObj.parentFn(); // compiles & runs & does nothing
Copyright@2014 Taylor & Francis Adair Dingle All Rights Reserved
How to choose design? • Soiware design is not a ‘one size fits all’ approach. • Different intents yield different designs. • Code reuse most feasible with clearly structured design • Inheritance supports
– Type extensibility – Polymorphism – Heterogeneous collec2ons (see chapter 7)
• Composi2on provides – Internal control – Flexibility and, possibly, reduced overhead
• Encapsula2on via composi2on or containment – isolates unstable code and allows one to wrap interfaces
Copyright@2014 Taylor & Francis Adair Dingle All Rights Reserved
Inheritance
• Appropriate when subtype checking needed – Client need not check for subtype – Class designer need not check for subtype – Subclass provides ‘automa2c’ subtype check (via compiler)
• Automa2c type associa2on • Class hierarchy sets up type extensibility
– New subtype added easily – No cut&paste fixes – Code not briSle: new subtype does not ‘break’ code
Copyright@2014 Taylor & Francis Adair Dingle All Rights Reserved
Example 6.7 C++ Monolithic class for Icon Movement
class Icon { float speed, glow, energy;
int x, y;
int subtype; //spinner, slider or hopper bool clockwise; // need for spinner
bool expand; // need for spinner
bool vertical; // need for slider int distance; // need for slider
bool visible; // need for hopper
int xcoord, ycoord; // need for hopper
void spin(); // functionality for spinner
void slide(); // functionality for slider
void hop(); // functionality for hopper public:
…
Copyright@2014 Taylor & Francis Adair Dingle All Rights Reserved
Example 6.7 C++ Monolithic class … con2nued public: // constructor must set subtype: client must pass value
Icon(unsigned value) { … subtype = value; // use enum for readability // and then use conditional to set associated fields } // tedious subtype checking: subtype drives movement void move() { if (subtype == 1) spin(); else if (subtype == 2) slide(); else hop(); } // again,tedious subtype checking:subtype drives flair
details void flair() { if (subtype == 1) … }
Copyright@2014 Taylor & Francis Adair Dingle All Rights Reserved
Example 6.8 Tedious Type expansion without Inheritance
// ALL methods in Icon that check subtype must be altered // in order to add new subtype ‘zigzag’ // ERROR PRONE software maintenance void Icon::move() { if (subtype == 1) spin();
else if (subtype == 2) slide();
else if (subtype == 3) hop(); else zigzag();
}
// ALL methods in Icon that check subtype must be altered // in order to add new subtype ‘zigzag’ => // flair() must also be altered since subtype drives details
Copyright@2014 Taylor & Francis Adair Dingle All Rights Reserved
Example 6.9 C++ Icon class hierarchy class Icon { protected:
float speed, glow, energy; int x, y;
public:
Icon(…) { … }
void move() { … }
void flair() { … }
… };
class Spinner: public Icon
{ protected:
bool clockwise, expand;
void spin();
public: Spinner(…):Icon(…) { … }
void move() { spin();… }
void flair() { … }
…
};
Copyright@2014 Taylor & Francis Adair Dingle All Rights Reserved
Example 6.9 Icon class hierarchy con2nued class Slider: public Icon { protected:
bool vertical; int distance;
void slide();
public:
Slider(…):Icon(…) { … }
void move() { slide();… }
… };
class Hopper: public Icon
{ protected:
bool visible;
int xcoord, ycoord;
void hop(); public:
Hopper(…):Icon(…) { … }
void move() { hop();… }
…
};
Copyright@2014 Taylor & Francis Adair Dingle All Rights Reserved
Example 6.9 Icon class hierarchy con2nued // easy to add new subtype ‘zigzag’ class zigzag: public Icon
{ protected: …
void zig();
void zag();
public:
zigzag(…):Icon(…) { … }
void move() { zig(); zag(); … } …
};
Copyright@2014 Taylor & Francis Adair Dingle All Rights Reserved
Code Reuse
• via Inheritance – Child classes automa2cally receive
• one parent (data) component • Access to all public/protected parent func2onality
• via Composi2on – Composing class automa2cally receives
• zero, one or more subObject • Access to all public subObject func2onality
=> Code reuse alone does not mo2vate design Copyright@2014 Taylor & Francis
Adair Dingle All Rights Reserved
Rela2onship Design & Code Reuse
• Composi2on – Type extension NOT essen2al – Type extension unlikely to be used alongside original – Interface may be suppressed – Cardinality of subObject may vary
• Inheritance – Type extension essen2al – Type extension LIKELY to be used alongside original – Interface may NOT be suppressed – Cardinality fixed at one (parent) is acceptable/preferred
Copyright@2014 Taylor & Francis Adair Dingle All Rights Reserved
Composite Principle Use composi,on in preference to inheritance • Formalizes prac22oners’ preference for composi2on
But Why? • Composi2on
– more flexible – offers more control over internal design than inheritance
• But remember, composi2on does NOT provide – Built-‐in subtype checking – Polymorphism – Support for heterogeneous collec2ons (see chapter 7) – Type extensibility
Copyright@2014 Taylor & Francis Adair Dingle All Rights Reserved
Principle of Least Knowledge
Every object assumes only the minimum possible about the structure and proper,es of other objects • Promotes low coupling • Applicable to both inheritance and composi2on rela2ons • Class design NOT dependent on
– private implementa2on details of any other class
• Design iden2fies – rela2onships – consequen2al effects of rela2onships
=> Class 2ed only to interface of parent/composed subobject
Copyright@2014 Taylor & Francis Adair Dingle All Rights Reserved
Open Closed Principle (OCP) A class should be open for extension and closed for modifica,on • Inheritance is an aSrac2ve design op2on for
– class hierarchies with implicit subtype selec2on to vary func2onality – Subs2tutability (see chapter 7) – Heterogeneous collec2ons (see chapter 7) – Type extensibility
• A good inheritance design adheres to OCP – individual classes preserved – type extensions are seamless
• OCP promotes soiware maintainability.
Copyright@2014 Taylor & Francis Adair Dingle All Rights Reserved