Upload
adair-dingle
View
81
Download
1
Embed Size (px)
Citation preview
Copyright@2014 Taylor & Francis Adair Dingle All Rights Reserved
Object-‐Oriented Design
Inheritance vs.
ComposiAon: Part II
Inheritance for Interface: Multiple Inheritance
Design QuesAons
• How to implement mulAple inheritance?
• What type is most important? – DisAnguish between potenAal base classes – Decide which type(s) to subordinate
Copyright@2015 Adair Dingle
Key ObservaAons
• Inheritance and composiAon BOTH provide reuse
• Interface inheritance is not true inheritance – but can serve to fulfill client needs
• Design impacts soSware maintainability Copyright@2015 Adair Dingle
Chapter 8: Design AlternaAves & PerspecAves
ComparaAve Design Design types and alterna/ves for client use
• Class design types • Design for Inheritance • Inheritance vs. ComposiAon • MulAple Inheritance • Design Principles
Copyright@2014 Taylor & Francis Adair Dingle All Rights Reserved
Why consider SoSware Design? • Design impacts soSware use
– Efficiency, OpAmizaAon (Inlining), Maintainability, … – Ease of subtype manipulaAon, heterogeneous collecAons, ... – Interface adaptaAon, type subordinaAon, …
• Design impacts soSware reuse – Type extensibility – Type checking, type extracAon
• Class designers should carefully consider design alternaAves • Different costs and benefits
– Inheritance vs composiAon – Exposed/echoed/wrapped interfaces – Type definiAon/idenAficaAon/extracAon
Copyright@2014 Taylor & Francis Adair Dingle All Rights Reserved
Class Design Types • Concrete – immediately usable
– Simple, efficient, standalone type – Inheritance NOT intended
• Abstract – not instanAable – Defines common interface for class hierarchy – Inheritance REQUIRED
• Node -‐-‐ Intermediate class in class hierarchy – Inherits interface – provides resoluAon or refined behavior – Inheritance anAcipated
Copyright@2014 Taylor & Francis Adair Dingle All Rights Reserved
Class Design Types -‐-‐ conAnued • Wrapper
– Isolates client from instable or proprietary interface – May echo porAon of wrapped interface – May augment/coalesce/modified wrapped behavior – Wrapped object replaceable without impact
• Delegate – Wrapped subObject – Replaceable, possibly polymorphic – ResponsibiliAes delegated to wrapped subObject
• Handle – Transparent resource manager – Tracks wrapped subObject – No alteraAon in wrapped behavior
Copyright@2014 Taylor & Francis Adair Dingle All Rights Reserved
Encapsulated SubObjects • Wrappers encapsulate exisAng types
– reusing (and possibly augmenAng or modifying) funcAonality – frequently isolate applicaAon programmer from unstable interfaces – wrapped subObject may be replaced without any impact – subObject’s interface, if echoed, oSen echoed in a modified fashion.
• Delegate is (wrapped) subObject – provides key funcAonality to the wrapper class – may be exchanged, replaced, stubbed out, and/or polymorphic.
• Handle promotes transparency – provides external access to internal funcAonality of wrapped subObject – e.g. smart pointer – Unlike wrappers, handles do not augment or modify subObject
funcAonality.
Copyright@2014 Taylor & Francis Adair Dingle All Rights Reserved
Abstract Classes
• Define interface for class hierarchy – Determine funcAonality accessible via heterogeneous collecAon
• May or may not provide default behavior • Require inheritance • EffecAve design with polymorphism
– May dilute cohesion if designed but unnecessary
Copyright@2014 Taylor & Francis Adair Dingle All Rights Reserved
Abstract Classes • A class is DESIGNED as abstract when • At least one method is undefined • only protected constructors provided => Client cannot instanAate instance of class
• C#/Java provide keyword abstract • code more readable and thus maintainable
• C++ does not provide keyword abstract
• UAlity of abstract classes remains the same – regardless of syntacAcal differences across languages
Copyright@2014 Taylor & Francis Adair Dingle All Rights Reserved
Example 8.4 Abstract Classes //C++: no keyword abstract C#/Java: just use keyword abstract // C++ => at least one method must be pure virtual class Toy
{ public:
virtual bool safe() = 0; …
};
//Abstract BY DESIGN (C++, C#, Java,…) // => protected constructor, no public constructor
class Vehicle
{ protected:
Vehicle();
public:
…
};
Copyright@2014 Taylor & Francis Adair Dingle All Rights Reserved
Example 8.5 Delegate Use class seminarAttendee // delegate could be object or pointer { // indirection supports postponed instantiation
idVerifier delegate;
…
void replaceDelegate(…) { idVerifier newImproved(…);
delegate = newImproved;
}
public:
…
// pass requests to delegate bool registerD() { return delegate.isSet() }
bool isValid() { return delegate.verify(); }
bool renew()
{ if (!registerD() || !isValid()) return false;
return (delegate.getAge() > 18)
}
};
Copyright@2014 Taylor & Francis Adair Dingle All Rights Reserved
Example 8.6 Polymorpic Delegate class HasADelegate { idVerifier delegate;
BaseType* polyD;
void replaceDelegate()
{ delete polyD;
if (…) polyD = new MinType(…);
else if (…) polyD = new MaxType(…);
else if (…) polyD = new MeanType(…);
}
public:
// simple echo
int getAge() [ return delegate.getAge(); }
// additional layer of indirection supports polymorphism
void dynamicProcess()
{ return polyD->process(); }
…
};
Copyright@2014 Taylor & Francis Adair Dingle All Rights Reserved
Table 8.4 Inheritance Effects
Copyright@2014 Taylor & Francis Adair Dingle All Rights Reserved
Motivation Characteristics Benefits Costs Code reuse Inheritance of Implementation
Reuse existing class May suppress/NOP interface
Reduce : --development time --cut & paste design --maintenance
Code complexity Increased coupling Decreased cohesion Unavoidable overhead Fixed cardinality Dependency on parent Lifetime association
Type extension Inheritance of Interface
Is-a relationship Subtype relevant
Type familiarity Substitutability Polymorphism Heterogeneity Extensibility
Inheritance vs. ComposiAon Both support Code Reuse
Inheritance supports type extensibility polymorphism heterogeneous collecAons
Inheritance provides built-‐in and efficient mechanism for type-‐checking promotes design clarity and maintainability
Copyright@2014 Taylor & Francis Adair Dingle All Rights Reserved
Inheritance vs. ComposiAon
ComposiAon affords the class designer more control • subObject may be manipulated in ways that a parent cannot • InstanAaAon may be postponed • subObjects may be replaced • Cardinality, lifeAme, associaAon and ownership may vary
– All fixed design for inheritance • Interfaces may be selecAvely echoed • Overhead can be avoided • Unstable types may be wrapped
Copyright@2014 Taylor & Francis Adair Dingle All Rights Reserved
Example 8.8 Inheritance vs ComposiAon
class B { protected:
virtual void filter(); public: … virtual void store();
}; class QueenInheritB: public B { public:
// keyword used for documentation // once virtual always virtual!! virtual void store() { B::store(); filter(); … } …
};
Copyright@2014 Taylor & Francis Adair Dingle All Rights Reserved
Example 8.8 conAnued
class QueenComposeB {
B subObject; public:
// cannot access protected B::filter() // virtual nature of B::store() not relevant void store()
{ subObject.store();
… }
…
};
Copyright@2014 Taylor & Francis Adair Dingle All Rights Reserved
Example 8.9 ComposiAon with Exposed Interface
class Be: public B { public:
… // make inherited protected method public void filter() { B::filter(); }
};
class QueenComposeB2
{ Be subObject;
public:
// can filter by using intermediary class void store()
{ subObject.store();
subObject.filter();
}
};
Copyright@2014 Taylor & Francis Adair Dingle All Rights Reserved
Example 8.10 Inheritance vs Polymorphic Subobjects
class flexQueen { B* subObjP; public:
// constructor can instantiate any B (sub)type object
// subObjP = 0 or subObjP = new Be or subObjP = Bee …
flexQueen()
{ subObjP = new B;
… // other choices
}
virtual void store()
{ subObjP->store(); // dynamic behavior }
void replaceB(B*& worker)
{ delete subObjP; subObjP = worker; worker = 0;
}
…
};
Copyright@2014 Taylor & Francis Adair Dingle All Rights Reserved
MulAple Inheritance
• Like single inheritance, mulAple inheritance – promotes type extensibility – supports polymorphism.
• MulAple inheritance increases design complexity – two divergent ancestral paths needed to understand class – Two-‐degree variance may compromise maintainability
• Two classic design difficulAes – AMBUGUITY: parental interfaces overlap – REDUNDANCY: common grandparent component
Copyright@2014 Taylor & Francis Adair Dingle All Rights Reserved
MulAple Inheritance
• Ambiguity easily resolved – Two parents define same funcAon signature => COMPILER ERROR – Child class must override doubly inherited funcAon
• redefine or direct call to specific parent => Descendant class definiAons compile
• Redundancy NOT easily resolved – Two parents share same ancestor – Child class inherits two copies of common ancestor – Duplicate copy cannot be suppressed easily
Copyright@2014 Taylor & Francis Adair Dingle All Rights Reserved
Example 8.12 Resolving Ambiguity: C++ MulAple Inheritance
class StudentEmployee: public Employee, public Student { …
public:
…
int getAge()
{ return Student::getAge(); }
int getSeniority()
{ return Employee::getAge(); } };
Copyright@2014 Taylor & Francis Adair Dingle All Rights Reserved
Type SubordinaAon
• Inheritance simulated via ComposiAon – One (or both) parent is defined as a subObject – Necessary when mulAple inheritance NOT supported (C#/Java)
• Class designer selects subObject & thus subordinates a type • subObject does not have visibility of a parent component
– its interface is not assumed – Its interface must be echoed if needed
• No is-‐a relaAonship to support type interchange in client code – Design changes not ‘automaAcally’ passed with compilaAon – No external subsAtutability for subObject – No heterogeneous collecAons typed to subObject
Copyright@2014 Taylor & Francis Adair Dingle All Rights Reserved
Type SubordinaAon
EffecAve design technique • Permits simulaAon of inheritance • adds flexibility and control over
– InstanAaAon – Cardinality – AssociaAon – LifeAme – Ownership – Interface
Copyright@2014 Taylor & Francis Adair Dingle All Rights Reserved
Example 8.17 C# StudentEmployee: Student parent
interface EmployeeI { … }
public class StudentEmployee3: Student, EmployeeI
{ // contain zero or more Employee components
private Employee e;
// interface forces echo of Employee functionality …
}
// why ‘Employee’ subordinated to ‘Student’?
Copyright@2014 Taylor & Francis Adair Dingle All Rights Reserved
Table 8.5 Simulate MulAple Inheritance using ComposiAon
Motivation Benefits Costs No provision for multiple inheritance in implementation language Clear subordinate parent type Efficiency Type depends on one parent for utility not interface
Variable cardinality Replaceable subobject Insulating layer Shield from parent Polymorphic subobject
Inconvenient loss of: -- Protected interface Design constrained by loss of: --Type familiarity --Substitutability --Polymorphism --Heterogeneity --Extensibility
Copyright@2014 Taylor & Francis Adair Dingle All Rights Reserved
Interface SegregaAon Principle
Interfaces should be small and contain only a few, related methods • Exalts interfaces as key design component • Promotes high cohesion and low coupling • Confines breadth of interface – Narrow interfaces focus design and imply specific uAlity. – Wide interfaces undermine cohesion and maintainability
• Targets interacAng class design – whether for inheritance or composiAon.
Copyright@2014 Taylor & Francis Adair Dingle All Rights Reserved
Program to Interface Not to ImplementaAon
Model func/onality, decoupled from implementa/on, by using abstract classes and interfaces. => Implementa/on can then vary independently. • Exalts interfaces as key design component • Upholds OOD abstracAon and encapsulaAon – Isolate client from volaAle/arbitrary implementaAon
• Drives complementary class design – whether for inheritance or composiAon.
Copyright@2014 Taylor & Francis Adair Dingle All Rights Reserved
Dependency Inversion Principle
High-‐level abstrac/ons are more stable. If dependencies exist, preferable that low-‐level abstrac/ons depend on high-‐level abstrac/ons • reinforces value of an extensible, possibly abstract, interface at the base of a class hierarchy.
• suggests choice when determining subordinate class – Client should be isolated from the least abstract type. – if any lower-‐level details change, client code is shielded.
Copyright@2014 Taylor & Francis Adair Dingle All Rights Reserved