none
Inheritance vs Polymorphism?

    Question

  • Hi!

    Something is not clear to me. My teacher in C# has not been able to fully explain to me why we should use inheritance and polymorphism when doing OOP?

    I have understood the concept of OOP, but why polymorphism?

    Can anyone just give me a real-life example for when to use polymorphism?


    And please, no smart answers like: "go and read...", "how can you not know this...", "bla bla bla...".



    I just want a simple, pedagogic and vivid answer.

    Thank you!

    Monday, September 08, 2008 7:24 PM

Answers

  • Using inheritance generally implies making use of polymorphism.  This type of polymorphism is type polymorphism, usually implemented through virtual methods.

    I generally recommend using inheritance for some is-a relationships--making sure that that principles like Liskov Substitution aren't violated.  This generally means the inherited type is either a specialization or overriding behaviour. 

    You generally use type polymorphism when you want to substitute one type for another.  This can be for generalization, expandability, etc.  Generalization through inheritance is when one bit of code wants only to deal with a generalization of a concept.  Shapes is a very common (but error-prone) example.  Drawing code may only need to deal with a Shape type and not want to be coupled to Square, Ellipse, Triangle, etc.  This decoupling also leads to expandability.  For example, if the drawing code only needs to now about Shape, it automatically can handle an infinite number of shapes, it does not need to change in order to support a new Shape-derived type.

    Polymorphism in the general case is a form of decoupling.  If allows one type of code to be decoupled at some level from other code.  Generally this is some sort of compile-time decoupling.  Parametric polymorphism (or method overloading) allows code that uses a specific method to be decoupled from a specific method and use whatever method matches the parameters used.  For example:

    1 Square square = new Square();  
    2 Triangle trianagle = new Triangle();  
    3 Draw(square);  
    4 Draw(triangle);  
    5  

    given
    void Draw(Square) {/* ... */}  
    void Draw(Triangle) { /* ... */ }  
     

    lines 3 and 4 are decoupled from a specific Draw method, the compiler picks which one to use at compile time.  Adding another Draw method means the existing code doesn't need to change.

    This makes code easier to write, easier to read, and easier to maintain.

    The above is bad example, you'll likely only want a Draw(Shape) method; I'm just too lazy to come up with another example.
    http://www.peterRitchie.com/blog
    • Marked as answer by Hamedeus Monday, September 08, 2008 8:57 PM
    Monday, September 08, 2008 8:08 PM
    Moderator

All replies

  • Using inheritance generally implies making use of polymorphism.  This type of polymorphism is type polymorphism, usually implemented through virtual methods.

    I generally recommend using inheritance for some is-a relationships--making sure that that principles like Liskov Substitution aren't violated.  This generally means the inherited type is either a specialization or overriding behaviour. 

    You generally use type polymorphism when you want to substitute one type for another.  This can be for generalization, expandability, etc.  Generalization through inheritance is when one bit of code wants only to deal with a generalization of a concept.  Shapes is a very common (but error-prone) example.  Drawing code may only need to deal with a Shape type and not want to be coupled to Square, Ellipse, Triangle, etc.  This decoupling also leads to expandability.  For example, if the drawing code only needs to now about Shape, it automatically can handle an infinite number of shapes, it does not need to change in order to support a new Shape-derived type.

    Polymorphism in the general case is a form of decoupling.  If allows one type of code to be decoupled at some level from other code.  Generally this is some sort of compile-time decoupling.  Parametric polymorphism (or method overloading) allows code that uses a specific method to be decoupled from a specific method and use whatever method matches the parameters used.  For example:

    1 Square square = new Square();  
    2 Triangle trianagle = new Triangle();  
    3 Draw(square);  
    4 Draw(triangle);  
    5  

    given
    void Draw(Square) {/* ... */}  
    void Draw(Triangle) { /* ... */ }  
     

    lines 3 and 4 are decoupled from a specific Draw method, the compiler picks which one to use at compile time.  Adding another Draw method means the existing code doesn't need to change.

    This makes code easier to write, easier to read, and easier to maintain.

    The above is bad example, you'll likely only want a Draw(Shape) method; I'm just too lazy to come up with another example.
    http://www.peterRitchie.com/blog
    • Marked as answer by Hamedeus Monday, September 08, 2008 8:57 PM
    Monday, September 08, 2008 8:08 PM
    Moderator
  • Thank you for your good answer!

    Now I have another question for you or anyone else: is it possible to integrate AJAX controls into a WPF Web Application? And why should I use a Silverlight Web Application when I can do much more with a WPF Web Application?
    Monday, September 08, 2008 8:59 PM
  • These sound alot like homework questions.
    David Morton - http://blog.davemorton.net/
    Monday, September 08, 2008 9:32 PM
    Moderator
  • Peter has more understanding of this than I do...

    Here's some things that have helped me...

    A single concrete class can only inherit from 1 parent class.  Thus in the vertical sense of inheritance, there is no polymorphism in C#,  that is not true in C++ however.  To me polymorphism means that an object can take on different shapes.  I had always thought that the Interface construct does that.  A class can look like a bunch of other things depending on the Interface implementations.  I don't believe this is the strict definition as Peter alludes, however I had always read that in C# it does not support polymorphism.

    Remember this, Inheritance is vertical and Interfaces are Horizontal.  Interfaces act like filters whereby anyone the uses it or implements it knows what the method signatures and or fields look like.  It's an agreement that allows for many different types of implemenatations of the abstracted components needed.  For example airplanes go() but they all go differently.  This is a Interface.  But all Airplanes must have a radio so that could be an abstracted vertical memeber for the concrete airplane class.  Airports tell airplanes to go() and get addressability to them horizontally from either one already being passed in, or creating and pointer to the interface via an instanciation like this  IAccelerate plane1 = new Airplane(airplanename);  plane1.go() would look exactly like plane2.go() etc.  You can see the commonality yet these could each be a different plane.
    Javaman
    Monday, September 08, 2008 11:01 PM
  • Mr. Javaman said:

    A single concrete class can only inherit from 1 parent class.  Thus in the vertical sense of inheritance, there is no polymorphism in C#


    Javaman



    That really doesn't make any sense.  The # of super-classes a sub-class can have doesn't afffect the abilty to use polymorphism. 
    http://www.peterRitchie.com/blog
    Tuesday, September 09, 2008 1:42 PM
    Moderator
  • Actually Peter it makes a lot of sense.  I believe MSFT has, like everything it does with other concepts, added new meaning to well defined terms.  All I meant in that statement is that in C#, a class can at most have just one super class.  That is not true in C++, and was one of the big selling points of C++ back in the early days of OOP.  If anyone looks up the definitions of POLYMORPHISM one finds that there are at least two major branches of meaning with 4 sub brances of differnt types of polymorphism.  I believe that MSFT has made a statement that blurs the distinction of the true meaning of it as is shown at this site.  http://msdn.microsoft.com/en-us/library/ms173152(VS.80).aspx  If you compare what is said at that site to this one, http://en.wikipedia.org/wiki/Polymorphism_(computer_science) (Note that there are disputes on these definitions)... You will see that the distinctions are indeed different.

    Until I read this post I had not known an implementation of an Interface to be POLYMORPHIC.  I had mistakenly always seen POLYMORPHISM to be vertical in nature only (parent/child classes).  I now cede to an expanded definition of POLYMORPHISM to be inclusive of Interface implementations because any time that happens it must have a base class to do the implementation.  The POLYMORHPISM in that case is that the instanciated class can now look and be referred to as its own TYPE and or referred to by it's INTERFACE type.  It is truly multi-faceted.


    Javaman
    • Edited by Mr. Javaman Wednesday, September 10, 2008 5:05 PM
    Tuesday, September 09, 2008 7:18 PM
  • Comments?
    Javaman
    Friday, September 12, 2008 6:52 PM
  • Mr. Javaman said:

    Comments?


    Javaman



    Are you looking for comments on something specific?

    Documentation for each programming language (that is generally object-oriented) defines polymorphism as it applies to that language.  I haven't seen a definition of polymorphism in a programming language text that doesn't define polymorphism in a general way.  Polymorphism is the ability of more than one "object" to respond to a particular "message".  Each language defines what a "message" is.  In most languages that is a method or function call.  In C# that would be method and delgate calls.  So, inheritance (of types and interfaces), method overloading, and delegates with the same paramters are run-time forms of polymorphism.
    http://www.peterRitchie.com/blog
    Friday, September 12, 2008 7:25 PM
    Moderator
  • I was just looking for some dialog on the subject, I can't seem to find a lot of folks that want to talk about it.  I was looking into the Strategy class you referred to in another post as a solution to a problem.  It seemed to me the deeper I studied it the more interesting it became.  Polymorphism being the cheif reason.  We all agree that abstraction is so important and thus it's the core value of implementing Abstract classes.  When the concrete implementations of that class also add Interface implementations, now we have a object that can literally take on many different facets.  I didn't realize the importance of that until I started thinking about the code maintainence cycle and or the changing specs need.  It dawned on me that if solution to a wide range of problems can be reduced to the Strategy pattern then we can have a controller remain consistent (never change in essence), and when new requirements show up we can only change the implementations of the concrete class where it's needed.  Using the concrete class as a "host" of the interface pattern we can take that object and pass it off to some other client or controller as a 100% different type.  The beauty of that is that the controller that uses that "other type" never sees it for all of the other types it could be...  

    So a class of Person could also implement a Employee interface.  Different controllers or clients would only need the Employee part while others would only need the Person parts.  The same object could be passed into both routines with a guarantee that only the stuff of Employee or Person would be worked on.  This allows for Employee changes down the road that will never impact the Person aspect of that object (if properly designed).  I think that is amazing.
    Javaman
    Friday, September 12, 2008 9:45 PM
  • Abstraction is the core of object-oriented design and programming.  Abstraction doesn't imply polymorphism; but polymorphism depends on abstraction.  (e.g. you can have an abstract class that is merely a container of reusable base functionality for implementors and never use polymorphism).

    For the most part, peoples views of polymorphism is somewhat narrow.  For example, only through inheritance.

    Other forms of polymorphism in C#:
    Delegate polymorphism:

    public void DoSomething(Predicate<String> predicate)  
    {  
      if(predicate(this.text))  
      {  
        // do something  
      }  
      else 
      {  
        // do something else  
      }  
    }  
     
    //...  
    DoSomething(this.IsTextCapitalized);  
    DoSomething(delegate(String text) { return text.Length > 0; }); 


    Copy and paste polymorphism:
    1   class One {  
    2    public void Method() {  
    3    }  
    4   }  
    5   class Two {  
    6    public void Method() {  
    7    }  
    8   }  
    9    One obj = new One();  
    10    obj.Method();  
    11  
    "Two obj = new Two();" could be pasted to line 9 and line 10 would still compile

    Duck-typing polymorphism
    At runtime, method signatures are tested via reflection and executed.

    http://www.peterRitchie.com/blog
    Monday, September 15, 2008 7:33 PM
    Moderator
  • Yes, I agree with you, in particular, I myself never viewed polymorphism as wide as is it until recently.  Nor did I really understand it's value in OOP until recently.

    The more I understand about both vertical (inheritance) and horizontal (interface) morphs, the more value I see in this thing they call "contract programming"  Not only that the power of up-casting and down-casting has become more obvious to me as I have finally turned the corner on Patterns. 

    So here's what I see that's so cool about this.  If we look at the horizontal aspect of OOP we're talking about some client code that takes something else (perhaps a class (superclass of subclass) or an Interface (which is just a pointer to a type)).  The concept for Horizontal mode polymorhpism is that a type is passed in (not rocket science in and of itself, but there's a lot to it when you are attempting to get something to "look" like something else).  We've always been able to pass parameters into other routines in the old modes of cascading programming styles, top-down design etc.  But now we have this newer ablity to not only pass entire class types, but we can mask the typing via up-casting, down-casting, and or by interfaces.  The legacy programming thought process of top-down get 'er done programming can still apply, but it should now be based on 'contracts' which should be 'strictly' followed.  When those contracts are strictly followed, then we can have assurance that "a small change here won't affect something there (related or unrelated)".  This is hugely powerful when one considers the ever-changing specification changes or scope creep or even code maint/bug fixes.  

    But as you say Peter, it all starts with abstraction, which anybody can learn.  It's a differnt mind set, than just code to the problem.  Instead it's look for commonality, extract it out, inherit the abstractions for is-a relationships to make the concrete classes, and then set up interfaces for all has-a relationships.  Now I've heard some folks suggest some interesting things like, you should never have more than 3 or 4 interface implementations per class.  I've heard others comment that you should never have a vertical inheritance chain larger than 3 or 4 as well.  But it seems to me, that many of the base classes in .NET itself has tons of vertical classes (heirarchically speaking)...

    I've heard a lot of folks say the biggest reason for OOP is code reuse.  I've also read that code reuse is no longer considered the biggest advantage in OOP.  The biggest advantage is in Code Maintainence.  SDLC studies show 60% of cost of the software lifecycle is in maint.  Only 20% is new development.  So if that's true then why isn't every shop in America running to their nearest software architect to come up with true OOP?  I think the answer is that they want something up and running now.  They feel that seeing something now is more important than sitting at the design booth drawing up plans.  Software is the only industry I know that has this profound belief that no architects are needed, ever.  It's code and go for the majority of shops today.  Or am I not seeing it right?

     
    Javaman
    Wednesday, September 17, 2008 11:42 AM