All Topics  
Polymorphism in object-oriented programming

 

   Email Print
   Bookmark   Link






 

Polymorphism in object-oriented programming



 
 
In simple terms, polymorphism is the ability of one type, A, to appear as and be used like another type, B. In strongly typed languages, this usually means that type A somehow derives from type B, or type A implements an interface that represents type B.

In non-strongly typed languages (dynamically typed languages) types are implicitly polymorphic to the extent they have similar features (fields, methods, operators).






Discussion
Ask a question about 'Polymorphism in object-oriented programming'
Start a new discussion about 'Polymorphism in object-oriented programming'
Answer questions from other users
Full Discussion Forum



Encyclopedia


In simple terms, polymorphism is the ability of one type, A, to appear as and be used like another type, B. In strongly typed languages, this usually means that type A somehow derives from type B, or type A implements an interface that represents type B.

In non-strongly typed languages (dynamically typed languages) types are implicitly polymorphic to the extent they have similar features (fields, methods, operators). In fact, this is one of the principal benefits (and pitfalls) of dynamic typing.

Operator Overloading
Operator overloading

In computer programming, operator overloading is a specific case of polymorphism in which some or all of operator s like +, =, or have different implementations depending on the types of their arguments....
 the numerical operators +,-,/,* allow polymorphic treatment of the various numerical types Integer, UnSigned Integer, Float, Decimal, etc; each of which have different ranges, bit patterns, and representations. Another common example is the use of the "+" operator which allows similar or polymorphic treatment of numbers (addition), strings (concatenation), and lists (attachment). This is a lesser used feature of polymorphism.

The primary usage of polymorphism in industry (object-oriented programming
Object-oriented programming

Object-oriented programming is a programming paradigm that uses "Object_" and their interactions to design applications and computer programs....
 theory) is the ability of objects
Object (computer science)

In its simplest embodiment, an object is an allocated region of storage. Since programming languages use variable#Computer_programmings to access objects, the terms object and variable are often used interchangeably....
 belonging to different types
Data type

A data type in programming languages is an attribute of a data which tells the computer something about the kind of data it is. This involves setting constraints on the datum, such as what values it can take and what operations may be performed upon it....
 to respond to method
Method (computer science)

In object-oriented programming, a method is a subroutine that is exclusively associated either with a class or with an object . Like a procedure in procedural programming languages, a method usually consists of a sequence of statement to perform an action, a set of input parameter to customize those actions, and possibly an output value...
, field, or property calls of the same name, each one according to an appropriate type-specific behavior. The programmer (and the program) does not have to know the exact type of the object in advance, and so the exact behavior is determined at run time (this is called late binding or dynamic binding
Dynamic binding

In object oriented programming, dynamic binding refers to determining the exact implementation of a request based on both the request name and the receiving object at the run-time....
).

The different objects involved only need to present a compatible interface
Interface (computer science)

Interface generally refers to an Abstraction_%28computer_science%29 that an entity provides of itself to the outside. This separates the methods of external communication from internal operation, and allows it to be internally modified without affecting the way outside entities interact with it, as well as provide Polymorphism in object-orien...
 to the clients (the calling routines
Subroutine

In computer science, a subroutine or subprogram is a portion of computer code within a larger computer program, which performs a specific task and is relatively independent of the remaining code....
). That is, there must be public or internal methods, fields, events, and properties with the same name and the same parameter sets
Parameter (computer science)

In computer programming, a parameter is a special kind of variable#In_computer_programming that refers to data that a subroutine receives to operate on....
 in all the Superclasses, Subclasses, and potentially Interfaces. In principle, the object types may be unrelated, but since they share a common interface, they are often implemented as Subclasses
Subclass (computer science)

In object-oriented programming, a subclass is a class that Inheritance some properties from its superclass .You can usually think of the subclass as being "a kind of" its superclass, as in a "a Manx is a kind of cat", or "a square is a kind of rectangle":...
 of the same Superclass
Superclass (computer science)

In computer science, a superclass is a class from which other classes are derived. A superclass is also called a parent class. The classes that are derived from a superclass are known as child classes, derived classes, or subclass ....
. Though it is not required, it is understood that the different methods will also produce similar results (for example, returning values of the same type).

Inheritance with Polymorphism

If a Dog is commanded to speak, she may emit a bark, while if a Pig is asked to speak, he may respond with an oink. Both inherit speak from Animal, but their subclass methods override the methods of the superclass, known as overriding polymorphism. Adding a walk method to Animal would give both Pig and Dog object's the same walk method.

Inheritance combined with polymorphism allows class B to inherit from class A without having to retain all features of class A; it can do some of the things that class A does differently. This means that the same "verb" can result in different actions as appropriate for a specific class. Calling code can issue the same command to their superclass or interface and get appropriately different results from each one.

Examples


C#


The ideal implementation of polymorphism in c# is to use interfaces stored in a common class API which has no user code dependencies.



// Assembly: Common Classes // Namespace: CommonClasses

public interface IAnimal

// Assembly: Animals // Namespace: Animals

public class AnimalBase

// Assembly: Animals // Namespace: Animals

public class Cat : AnimalBase, IAnimal

// Assembly: Animals // Namespace: Animals

public class Dog : AnimalBase, IAnimal

// Assembly: Program // Namespace: Program // References and Uses Assemblies: Common Classes, Animals

public class TestAnimals



The reason this is ideal is because then objects can be used in any assembly, regardless of any circular reference
Circular reference

A circular reference, sometimes referred to as a run-around, is a series of references where the last object references the first, thus causing the whole series of references to be unusable....
 issues present. This is a slightly modified implementation of the Strategy Design Pattern
Strategy pattern

In computer programming, the strategy pattern is a particular design pattern , whereby algorithms can be selected at runtime.In some programming languages, such as those without Polymorphism , the issues addressed by this pattern are handled through forms of Reflection , such as the native function pointer or function Delegation syntax....
. Implementing a base class is not required but is typically useful for code reuse through inheritance.

This example also uses generics
Generic programming

Generic programming is a style of computer programming in which algorithms are written in terms of to-be-specified-later types that are then instantiated when needed for specific types provided as parameters and was pioneered by Ada which appeared in 1983....
, which enable many things, including compile time type safety for collections, and no boxing, unboxing, or casting performance penalties. Combining interfaces, design patterns, and generics creates very flexible, extensible, readable, maintainable, high performance designs.

Delphi

unit polymorphism;

interface

type IAnimal = interface property Name : string read; function Talk : string; end;

TAnimalBase = class( TObject ) private fName : string public property Name : string read fName; constructor Create( aName : string ); virtual; end;

TCat = class( TAnimalBase, IAnimal ) public function Talk : string; end;

TDog = class( TAnimalBase, IAnimal ) public function Talk : string; end;

implementation

constructor TAnimalBase.Create( aName : string ); begin fName := aName; end;

function TCat.Talk : string; begin result := 'Meowww!'; end;

function TDog.Talk : string; begin result := 'Arf! Arf!'; end;

end.

Python


myString = 'Hello, world!' myList = [0, 'one', 1, 'two', 3, 'five', 8]

print myString[:5] # prints Hello print myList[:5] # prints [0, 'one', 1, 'two', 3]

print 'e' in myString # prints True print 5 in myList # prints False

However, the most common examples of polymorphism are found in custom classes. Consider the example below, where two subclasses (Cat and Dog) are derived from an Animal superclass. Two Cat objects and one Dog are instantiated and given names, and then they are gathered in an array "animals" and their "talk" method is called. class Animal: def __init__(self, name): # Constructor of the class self.name = name

class Cat(Animal): def talk(self): return 'Meow!'

class Dog(Animal): def talk(self): return 'Woof! Woof!'

animals = [Cat('Missy'), Cat('Mr. Bojangles'), Dog('Lassie')]

for animal in animals: print animal.name + ': ' + animal.talk

  1. prints the following:
  2. Missy: Meow!
  3. Mr. Bojangles: Meow!
  4. Lassie: Woof! Woof!


Note that Python makes polymorphism particularly easy to write, since the language is dynamically (and implicitly) typed: a name can be bound to objects of any type (or class) without having to explicitly specify the type, and a list holds mixed type (unlike a C array or a Java array, be it generic or not). Note the inevitable trade-off though: a language that generates fewer compile-time errors tends to generate more run-time errors, requiring explicit (unit) testing.

Dynamic language performance is hindered by the extra checks and searches that occur at each call site. Straightforward implementations have to repeatedly search class precedence lists for members and potentially resolve overloads on method argument types each time you execute a particular line of code. In an expression such as o.m(x, y) or x + y, dynamic languages need to check exactly what kind of object o is, what is m bound to for o, what type x is, what type y is, or what "+" means for the actual runtime type of x and y. In a statically typed language (or with enough type hints in the code and type inferencing), you can emit exactly the instructions or runtime function calls that are appropriate at each call site. You can do this because you know from the static types what is needed at compile time.

Dynamic languages provide great productivity enhancements and powerful terse expressions due to their dynamic capabilities. However, in practice code tends to execute on the same types of objects each time. This means you can improve performance by remembering the results of method searches the first time a section of code executes. For example, with x + y, if x and y are integers the first time that expression executes, we can remember a code sequence or exactly what runtime function performs addition given two integers. Then each time that expression executes, there is no search involved. The code just checks that x and y are integers again, and dispatches to the right code with no searching. The result can literally be reduced to inlined code generation with a couple of type checks and an add instruction, depending on the semantics of an operation and method caching mechanisms used.

C++


  1. include
  2. include


using namespace std;

class Animal ;

class Cat : public Animal ;

class Dog : public Animal ;

// prints the following: // // Missy: Meow! // Mr. Bojangles: Meow! // Lassie: Arf! Arf! // int main



Note that the talk method is explicitly declared as virtual. This is because polymorphic method calls have relatively high overhead in C++ . This overhead is lessened by treating all method calls as non-polymorphic, unless explicitly marked as virtual by the developer.

Java

interface Animal

abstract class AnimalBase implements Animal

class Cat extends AnimalBase

class Dog extends AnimalBase

public class TestAnimals



Perl

Polymorphism in Perl is inherently straightforward to write because of the languages use of sigils
Sigil (computer programming)

In computer programming, a sigil is a symbol attached to a variable name, showing the variable's datatype or Scope . The term was first applied to Perl usage by Philip Gwyn in 1999 to replace the more cumbersome "funny character in front of a variable name"....
 and references
Reference (computer science)

In computer science, a reference is an object containing information about how to locate and access the particular data item, as opposed to containing the data itself....
. This is the Animal example in standard OO Perl...




my $a = Cat->new('Missy'); my $b = Cat->new('Mr. Bojangles'); my $c = Dog->new('Lassie');

for my $animal ( $a, $b, $c )

  1. prints the following:
  2. Missy: Meow
  3. Mr. Bojangles: Meow
  4. Lassie: Woof! Woof!


This means that Perl can also apply Polymorphism to the method call. Example below is written using the Moose module to show modern OO practises in Perl (and is not needed for method Polymorphism).....




my @animals = ( Cat->new( name => 'Missy' ), Cat->new( name => 'Mr. Bojangles' ), Dog->new( name => 'Lassie' ), );

for my $animal ( @animals )

  1. prints the following:
  2. Missy: talk => Meow
  3. Missy: likes => Milk
  4. Mr. Bojangles: talk => Meow
  5. Mr. Bojangles: likes => Milk
  6. Lassie: talk => Woof! Woof!
  7. Lassie: likes => Bone


Visual Basic .NET


One way of doing polymorphism is through the definition and implementation of a common interface. Consider the example below, where two subclasses (Cat and Dog) implement the IAnimal interface. Two Cat objects and one Dog are instantiated and given names, and then they are gathered in a list and their talk method is called.

Namespace std

Public Interface IAnimal ReadOnly Property Name As String Function Talk As String End Interface

Public Class Cat Implements IAnimal

Private mName As String

Sub New(ByVal name As String) mName = name End Sub

Public ReadOnly Property Name As String Implements IAnimal.Name Get Return mName End Get End Property

Public Function Talk As String Implements IAnimal.Talk Return "Meow!" End Function End Class

Public Class Dog Implements IAnimal

Private mName As String

Sub New(ByVal name As String) mName = name End Sub

Public ReadOnly Property Name As String Implements IAnimal.Name Get Return mName End Get End Property

Public Function Talk As String Implements IAnimal.Talk Return "Arf! Arf!" End Function End Class

Public Module TestAnimals

' Prints the following: ' ' Missy: Meow! ' Mr. Bojangles: Meow! ' Lassie: Arf! Arf! Public Sub Main Dim animals(2) As IAnimal animals(0) = New Cat("Missy") animals(1) = New Cat("Mr. Bojangles") animals(2) = New Dog("Lassie")

For Each a As IAnimal In animals Console.Out.WriteLine(": ", a.Name, a.Talk) Next a

End Sub End Module

End Namespace

Xbase++


  1. include "class.ch"


// // This program prints: // // Missy Meow! // Mr. Bojangles Meow! // Lassie Bark! // Press any key to continue... //

///////////////////////////// // PROCEDURE Main // /////////////////////////////

LOCAL aAnimals := Array(3) LOCAL i

aAnimals[1] := Cat:New("Missy") aAnimals[2] := Cat:New("Mr. Bojangles") aAnimals[3] := Dog:New("Lassie")

FOR i:=1 TO LEN(aAnimals) ? aAnimals[i]:Name + " " + aAnimals[i]:Talk NEXT i

WAIT

RETURN

///////////////////////////// // CLASS Animal // /////////////////////////////

EXPORTED: VAR Name READONLY

METHOD Init DEFERRED CLASS METHOD Talk ENDCLASS

METHOD Animal:Init( cName ) Name := cName RETURN Self

///////////////////////////// // CLASS Dog FROM Animal // ///////////////////////////// EXPORTED: METHOD Talk ENDCLASS

METHOD Dog:Talk RETURN "Bark!"

///////////////////////////// // CLASS Cat FROM Animal // ///////////////////////////// EXPORTED: METHOD Talk ENDCLASS

METHOD Cat:Talk RETURN "Meow!"

Ruby


class Thing def who_am_I puts "I'm a thing!" end end

class AnotherThing def who_am_I puts "I'm another thing!" end end

  1. adds 'who_am_I' method to class String:
class String def who_am_I puts "I'm a plain Ruby String!" end end

things = [Thing.new, AnotherThing.new, 'boring string'] things.each
  1. prints:
  2. I'm a thing!
  3. I'm another thing!
  4. I'm a plain Ruby String!


Parametric Polymorphism

In object-oriented programming languages, the term polymorphism has different, but related meanings; one of these, parametric polymorphism, is known as generic programming
Generic programming

Generic programming is a style of computer programming in which algorithms are written in terms of to-be-specified-later types that are then instantiated when needed for specific types provided as parameters and was pioneered by Ada which appeared in 1983....
 in the Object Oriented Programming Community and is supported by many languages including C++
C++

C++ is a general-purpose programming language. It is regarded as a middle-level language, as it comprises a combination of both high-level programming language and low-level programming language language features....
, C# and Java
Java (programming language)

Java is a programming language originally developed by James Gosling at Sun Microsystems and released in 1995 as a core component of Sun Microsystems' Java ....
.

Generics
Generic programming

Generic programming is a style of computer programming in which algorithms are written in terms of to-be-specified-later types that are then instantiated when needed for specific types provided as parameters and was pioneered by Ada which appeared in 1983....
 allow you compile time type safety and other benefits and/or disadvantages depending on the language's implementation.

C++ implements parametric polymorphism through templates. The use of templates requires the compiler to generate a separate instance of the templated class or function for every permutation of type parameters used with it, which can lead to code bloat and difficulty debugging
Generic programming

Generic programming is a style of computer programming in which algorithms are written in terms of to-be-specified-later types that are then instantiated when needed for specific types provided as parameters and was pioneered by Ada which appeared in 1983....
. A benefit C++ templates have over Java and C# is that they allow for template metaprogramming, which is a way of pre-evaluating some of the code at compile-time rather than run-time.

Java parametric polymorphism is called generics and implemented through type erasure.

C# parametric polymorphism is called generics and implemented by reification
Reification (computer science)

Reification is a process through which a computable/addressable object - a resource - is created in a system, as a proxy for a non computable/addressable object....
, making C# the only language of the three which supports parametric polymorphism as a first class member of the language. This design choice is leveraged to provide additional functionality, such as allowing reflection with preservation of generic types
Generic programming

Generic programming is a style of computer programming in which algorithms are written in terms of to-be-specified-later types that are then instantiated when needed for specific types provided as parameters and was pioneered by Ada which appeared in 1983....
, as well as alleviating some of the limitations of erasure (such as being unable to create generic arrays). This also means that there is no performance hit from runtime casts and normally expensive boxing conversions. When primitive and value types are used as generic arguments, they get specialized implementations, allowing for efficient generic collections and methods.

Mitigating circular dependency references using polymorphism in C#

Problem

Assembly Name:Logger
Dependencies:Data Access Layer
Methods:LogError(string error)

Assembly Name: Data Access Layer
Dependencies: SqlClient, System.Data
Methods:WriteData(string data)

With this design, writing error messages from catch statements and writing them to the Logger class from the Data Access Layer class would not work due to a circular dependency reference.

Example of broken class in Data Access Layer



public static class WriteData

Solution

Assembly Name:CommonClasses
Dependencies:None
Interfaces:ILogger

Assembly Name:Data Access Layer
Dependencies:SqlClient, System.Data, CommonClasses
Methods:WriteData(string data, ILogger logger)

Example of working class in Data Access Layer



public static class WriteData



It is technically a better practice to have a static initialization function the caller uses to pass in a concrete class which implements the ILogger interface to the common classes API which caches it in a static private field with an associated public or internal property for reuse throughout the application without having to reinstantiate the object. Just try to avoid using static data, and if it has to be used, make sure to synchronize access to it for thread safety.

See also

  • Inheritance (computer science)
    Inheritance (computer science)

    In object-oriented programming, inheritance is a way to form new class es using classes that have already been defined. The inheritance concept was invented in 1967 for Simula....
  • Polymorphic association
    Polymorphic association

    Polymorphic association is a term used in discussions of Object-Relational Mapping with respect to the problem of representing in the relational database domain, a relationship from one Class to multiple classes....
  • Generic programming
    Generic programming

    Generic programming is a style of computer programming in which algorithms are written in terms of to-be-specified-later types that are then instantiated when needed for specific types provided as parameters and was pioneered by Ada which appeared in 1983....


External links