Polymorphism – “The occurrence of different forms, stages, or types in individual organisms or in organisms of the same species, independent of sexual variations.” (dictionary.com). By that definition, we could assume polymorphism is a programmatic way to represent the same object through multiple states or stages. That’s great, but probably still unclear to many of us. What it really means is this: programming to an interface or base class without regard to an object’s concrete class.
If you are familiar with design patterns, even on a rudimentary level, you should be getting a picture in your mind of what this means. In fact, polymorphism is probably the single greatest facilitator for patterns-based programming. It allows us to organize similar objects in a logical way such that calling code does not have to worry about specific types; rather, we code to an expected interface or base class. The more a software application is abstracted, the more flexible it becomes – and polymorphism is one of the best ways to abstract behaviors.
For example, consider a class called Person. We can subclass Person with classes called David, Charles, and Alejandro. Person has an abstract method called AcceptFeedback(), which all subclasses implement. That means that any code using any subclasses of the Person base class can call the AcceptFeedback() method with confidence, knowing that the class itself handles logic that would otherwise appear in a conditional. You do not have to check whether the object is a David or an Alejandro, just that it is a Person. The effect is that your code is written to the lowest common denominator – the Person class.
The Person class in this example could also be created as an interface. There are some differences, primarily that an interface imparts no behavior, only a set of rules, so to speak. A Person interface would say “you must support the AddFeedback() method” whereas a Person class could provide some default code for the AddFeedback() method, saying “if you choose not to support AddFeedback(), you will be provided with a default implementation.” Choosing interfaces or base classes is the subject for another article entirely, but in general, if you need a default implementation for a method, provide it through a base class. If you are simply outlining a set of expectations for your classes, then use an interface.