Object-oriented design: Inheritance subtyping (vs. Composition)

31
Copyright@2014 Taylor & Francis Adair Dingle All Rights Reserved ObjectOriented Design Inheritance vs. Composi2on: Part I Inheritance for Subtyping: Structural Reuse

Transcript of Object-oriented design: Inheritance subtyping (vs. Composition)

Page 1: Object-oriented design: Inheritance subtyping (vs. Composition)

Copyright@2014 Taylor & Francis Adair Dingle All Rights Reserved

Object-­‐Oriented  Design    

Inheritance    vs.    

Composi2on:  Part  I  

   Inheritance for Subtyping: Structural Reuse

Page 2: Object-oriented design: Inheritance subtyping (vs. Composition)

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

Page 3: Object-oriented design: Inheritance subtyping (vs. Composition)

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

Page 4: Object-oriented design: Inheritance subtyping (vs. Composition)

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

Page 5: Object-oriented design: Inheritance subtyping (vs. Composition)

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

Page 6: Object-oriented design: Inheritance subtyping (vs. Composition)

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

Page 7: Object-oriented design: Inheritance subtyping (vs. Composition)

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

Page 8: Object-oriented design: Inheritance subtyping (vs. Composition)

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

Page 9: Object-oriented design: Inheritance subtyping (vs. Composition)

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

Page 10: Object-oriented design: Inheritance subtyping (vs. Composition)

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

Page 11: Object-oriented design: Inheritance subtyping (vs. Composition)

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

Page 12: Object-oriented design: Inheritance subtyping (vs. Composition)

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

Page 13: Object-oriented design: Inheritance subtyping (vs. Composition)

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

Page 14: Object-oriented design: Inheritance subtyping (vs. Composition)

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

Page 15: Object-oriented design: Inheritance subtyping (vs. Composition)

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

Page 16: Object-oriented design: Inheritance subtyping (vs. Composition)

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

Page 17: Object-oriented design: Inheritance subtyping (vs. Composition)

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

Page 18: Object-oriented design: Inheritance subtyping (vs. Composition)

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

Page 19: Object-oriented design: Inheritance subtyping (vs. Composition)

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

Page 20: Object-oriented design: Inheritance subtyping (vs. Composition)

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

Page 21: Object-oriented design: Inheritance subtyping (vs. Composition)

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

Page 22: Object-oriented design: Inheritance subtyping (vs. Composition)

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

Page 23: Object-oriented design: Inheritance subtyping (vs. Composition)

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

Page 24: Object-oriented design: Inheritance subtyping (vs. Composition)

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

Page 25: Object-oriented design: Inheritance subtyping (vs. Composition)

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

Page 26: Object-oriented design: Inheritance subtyping (vs. Composition)

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

Page 27: Object-oriented design: Inheritance subtyping (vs. Composition)

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

Page 28: Object-oriented design: Inheritance subtyping (vs. Composition)

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

Page 29: Object-oriented design: Inheritance subtyping (vs. Composition)

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

Page 30: Object-oriented design: Inheritance subtyping (vs. Composition)

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

Page 31: Object-oriented design: Inheritance subtyping (vs. Composition)

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