Try to describe polymorphism as easy as you can [closed]
Asked Answered
B

24

61

How can polymorphism be described in an easy-to-understand way?

We can find a lot of information about the subject on the Internet and books, like in Type polymorphism. But let's try to make it as simple as we can.

Bouffant answered 16/10, 2008 at 22:0 Comment(5)
...and make it long and easy to copy-and-paste. Homework? ;)Connell
LOL , no.. my homework are way far from meBouffant
Well, I'm glad you have a sense of humor.Connell
Note well: most of the replies to this question are confusing polymorphism with dynamic dispatch on the first argument. Polymorphism isn't particularly useful without some kind of dynamic dispatch, but it is possible. Think of e.g. a notional Java Object without any members, always needing casts.Bournemouth
Howz that : A boy starts LOVE with the word FRIENDSHIP but A girl ends LOVE with the same word FRIENDSHIP.Word is the same, but functionality is different. That's LOL polymorphism.Hitt
T
32

This is from my answer from a similiar question. Here's an example of polymorphism in pseudo-C#/Java:

class Animal
{
    abstract string MakeNoise ();
}

class Cat : Animal {
    string MakeNoise () {
        return "Meow";
    }
}

class Dog : Animal {
    string MakeNoise () {
        return "Bark";
    }
}

Main () {
   Animal animal = Zoo.GetAnimal ();
   Console.WriteLine (animal.MakeNoise ());
}

The Main() method doesn't know the type of the animal and depends on a particular implementation's behavior of the MakeNoise() method.

Talton answered 16/10, 2008 at 22:7 Comment(4)
Note that you're describing dynamic dispatch (which requires polymorphism), not polymorphism itself.Bournemouth
An example isn't a description :PGreenshank
This example is not really sufficient, since they both just return a String. In my opinion, a minimally sufficient example would have a different BEHAVIOR for each method...Surbeck
I am more explained by code than essays!Rodman
U
71

Two objects respond to the same message with different behaviors; the sender doesn't have to care.

Unmuzzle answered 16/10, 2008 at 22:17 Comment(1)
This should be the accepted answerLuna
R
33

Every Can with a simple pop lid opens the same way.
As a human, you know that you can Open() any such can you find.

When opened, not all cans behave the same way.
Some contain nuts, some contain fake snakes that pop out.
The result depends on what TYPE of can, if the can was a "CanOfNuts" or a "CanOfSnakes", but this has no bearing on HOW you open it. You just know that you may open any Can, and will get some sort of result that is decided based on what type of Can it was that you opened.

pUnlabledCan->Open(); //might give nuts, might give snakes. We don't know till we call it

Open() has a generic return type of "Contents" (or we might decide no return type), so that open always has the same function signature.

You, the human, are the user/caller.
Open() is the virtual/polymorphic function.
"Can" is the abstract base class.
CanOfNuts and CanOfSnakes are the polymorphic children of the "Can" class.
Every Can may be opened, but what specifically it does and what specific tye of contents it returns are defined by what sort of can it is.
All that you know when you see pUnlabledCan is that you may Open() it, and it will return the contents. Any other behaviors (such as popping snakes in your face) are decided by the specific Can.

Roadster answered 16/10, 2008 at 23:21 Comment(0)
T
32

This is from my answer from a similiar question. Here's an example of polymorphism in pseudo-C#/Java:

class Animal
{
    abstract string MakeNoise ();
}

class Cat : Animal {
    string MakeNoise () {
        return "Meow";
    }
}

class Dog : Animal {
    string MakeNoise () {
        return "Bark";
    }
}

Main () {
   Animal animal = Zoo.GetAnimal ();
   Console.WriteLine (animal.MakeNoise ());
}

The Main() method doesn't know the type of the animal and depends on a particular implementation's behavior of the MakeNoise() method.

Talton answered 16/10, 2008 at 22:7 Comment(4)
Note that you're describing dynamic dispatch (which requires polymorphism), not polymorphism itself.Bournemouth
An example isn't a description :PGreenshank
This example is not really sufficient, since they both just return a String. In my opinion, a minimally sufficient example would have a different BEHAVIOR for each method...Surbeck
I am more explained by code than essays!Rodman
M
20

The simplest description of polymorphism is that it is a way to reduce if/switch statements.

It also has the benefit of allowing you to extend your if/switch statements (or other people's ones) without modifying existing classes.

For example consider the Stream class in .NET. Without polymorphism it would be a single massive class where each method implements a switch statement something like:

public class Stream
{
    public int Read(byte[] buffer, int offset, int count)
    {
        if (this.mode == "file")
        {
            // behave like a file stream
        }
        else if (this.mode == "network")
        {
            // behave like a network stream
        }
        else // etc.
    }
}

Instead we allow the runtime to do the switching for us in a more efficient way, by automatically choosing the implementation based on the concrete type (FileStream, NetworkStream), e.g.

public class FileStream : Stream
{
    public override int Read(byte[] buffer, int offset, int count)
    {
        // behave like a file stream
    }
}

public class NetworkStream : Stream
{
    public override int Read(byte[] buffer, int offset, int count)
    {
        // behave like a network stream
    }
}
Mweru answered 16/10, 2008 at 22:50 Comment(4)
I like this explanation because it describes how polymorphism is actually useful.Conias
Dynamic dispatch is a way to reduce switch/if statements. Multiple dispatch using pattern matching and perhaps destructuring for convenience would be a more flexible solution, and wouldn't require polymorphism at all. Polymorphism != dynamic dispatch.Bournemouth
I didn't say it was the only way to reduce if statements, just that it was a way to do so. It depends on what language you're working in as to which paradigm would be more appropriate.Mweru
I like the explanation, but I hate real programming examples. Though I do wonder if they are better or worse for communicating the point....Surbeck
G
10

Poly: many
Morphism: forms / shapes

Gentianaceous answered 16/10, 2008 at 23:52 Comment(0)
H
6

The Actor vs. the Character (or Role)

Heathheathberry answered 16/10, 2008 at 22:6 Comment(2)
Interesting... or maybe the "role" (instead of character).Introject
Or better still, One role, many actors. I think this is clearly the best and most concise explanation -- but I may be biased as a bardolate.Introject
M
6

Apples and oranges are both fruit. Fruit can be eaten. Hence, both apples and oranges can be eaten.

The kicker? You eat them differently! You peel the oranges, but not the apples.

So the implementation differs, but the end result is the same, you eat the fruit.

Minsk answered 20/12, 2008 at 21:34 Comment(0)
T
4

If it walks like a duck and quacks like a duck, then you can treat it as a duck anywhere you need a duck.

Tunic answered 16/10, 2008 at 22:44 Comment(5)
I think that's more a description of duck typing than polymorphism. It's a subtly different relationship ("looks like a" rather than "is a").Mweru
@Greg It's the same principle, you're just hung up on the terminology.Fuzee
it's best if it implements the IDuck interfaceUnmuzzle
@Fuzee - it isn't the same principle. With polymorphism something can look exactly like a duck but not be one. As I said, it's subtly different.Mweru
@Greg - ok, there IS a subtle difference but I don't think it's "looks like a" vs. "is a". "is a" implies inheritance, while I guess you could say that duck typing is "acts like a", which I would argue is still a form of polymorphism.Tunic
S
3

This is a better article actually

Polymorphism allows Objects to "Look" the same, but behave in different ways. The usual example is to take an animal base class with a Speak() Method, A dog subclass would emit a Bark whereas a Pig subclass would emit an oink.

The 5 second short answer most people use so other developers can get their head around Polymorphism is overloading and overriding

Savarin answered 16/10, 2008 at 22:9 Comment(0)
L
2

Same syntax, different semantics.

Levon answered 17/10, 2008 at 4:30 Comment(0)
E
1

Simplest way to describe it: a verb that can apply to more than one kind of object.

Everything else, as Hillel said, is just commentary.

Ediva answered 16/10, 2008 at 23:53 Comment(2)
You are describing dynamic dispatch, not polymorphism.Bournemouth
en.wikipedia.org/wiki/Dynamic_dispatch I do not think it means what you seem to think it means.Ediva
G
1

Polymorphism is treating things abstractly by relying on knowledge of a common "parent" (think heirarchies like Animal as a parent of Dogs and Cats).

For example, all Animals can breathe oxygen, and while they may each do this differently you could design a facility that provides oxygen for Animals to breathe, supporting both Dogs and Cats.

As a little extra, you can do this even though Animal is an "abstract" identifier (there is no real "Animal" thing, just types of Animals).

Greenshank answered 17/10, 2008 at 0:20 Comment(0)
B
1

Polymorphism is the storing of values of more than one type in a location of a single type.

Note that most of the other answers to this question, at the time of my writing, are actually describing dynamic dispatch, not polymorphism.

Dynamic dispatch requires polymorphism, but the reverse is not true. One could imagine a language very similar to Java or C# but whose System.Object had no members; typecasting would be necessary before doing anything with the value. In this notional language, there would be polymorphism, but not necessarily virtual methods, or any other dynamic dispatch mechanisms.

Dynamic dispatch is the related but distinct concept, well enough described in most of the other answers. However, the way it normally works in object-oriented languages (selecting a function based on the first ('this' or 'Self') argument type) is not the only way it can work. Multiple dispatch is also possible, where the selection is applied across the types of all the arguments.

Similarly, overload resolution and multiple dispatch are exact analogues of one another; overload resolution is multiple dispatch applied to static types, while multiple dispatch is overload resolution applied to runtime types stored in polymorphic locations.

Bournemouth answered 17/10, 2008 at 1:15 Comment(9)
Covariance and contravariance is the term I would use, not dynamic dispatch.Formalism
Covariance and contravariance are about a related but different issue again; they are comparative terms that describe how one subtyping relationship changes with respect to another. They are not specific to polymorphism; consider e.g. co/contravariance in Java generic wildcards, or CLR generics.Bournemouth
Co/contravariance are like comparison operators; "this type is covariant to that", one would say. Dynamic dispatch is a mechanism, when fully specified, it does something.Bournemouth
Your own Wikipedia link says "dynamic dispatch is the process of mapping a message to a specific sequence of code (method) at runtime". Polymorphism is not a runtime trick. Its a compile time trick done by covariance.Formalism
As I read further, it appears that C++'s VTables are used during runtime to pick the appropriate method, so I stand corrected...However this seems very odd, as C++ should be able to infer the correct types during compilation.Formalism
Jonathan Holland, polymorphism is something that happens at runtime. All compiled code is "compile time tricks". And covariance is not a mechanism.Bournemouth
Re your comment on vtables: no compiler for a language that is Turing complete that supports polymorphism can infer the runtime types at compile time for all cases, because of the halting problem.Bournemouth
Good to know :) Can you go into detail about the halting problem?Formalism
Wikipedia is decent enough on the topic: Halting ProblemBournemouth
P
1

Polymorphism is what you get when the same method applies to multiple classes. For example, both a String and a List might have "Reverse" methods. Both methods have the same name ("Reverse"). Both methods do something very similar (reverse all the characters or reverse the order of the elements in the list). But the implementation of each "Reverse" method is different and specific to its class. (In other words, the String reverses itself like a string, and the List reverses itself like a list.)

To use a metaphor, you could say "Make Dinner" to a French chef or to a Japanese chef. Each would perform "make dinner" in their own characteristic way.

The practical result is that you could create a "Reversing Engine" that accepts an object and calls "Reverse" on it. As long as the object has a Reverse method, your Reversing Engine will work.

To extend the chef analogy, you could build a "Waiterbot" that tells chefs to "Make Dinner". The Waiterbot doesn't have to know what type of dinner is going to be made. It doesn't even have to make sure it's talking to a chef. All that matters is that the "chef" (or fireman, or vending machine, or pet food dispenser) knows what to do when it's told to "Make Dinner".

What this buys you as a programmer is fewer lines of code and either type-safety or late binding. For example here's an example with type safety and early binding (in a c-like language that I'm making up as I go):

class BankAccount {
    void SubtractMonthlyFee
}

class CheckingAccount : BankAccount {}

class SavingsAccount : BankAccount {}

AssessFee(BankAccount acct) {
    // This will work for any class derived from
    //   BankAccount; even classes that don't exist yet
    acct.SubtractMonthlyFee
}

main() {

    CheckingAccount chkAcct;
    SavingsAccount saveAcct;

    // both lines will compile, because both accounts
    //   derive from "BankAccount". If you try to pass in
    //   an object that doesn't, it won't compile, EVEN
    //   if the object has a "SubtractMonthlyFee" method.
    AssessFee(chkAcct);
    AssessFee(saveAcct);
}

Here's an example with no type safety but with late binding:

class DatabaseConnection {
    void ReleaseResources
}

class FileHandle {
    void ReleaseResources
}

FreeMemory(Object obj) {
    // This will work for any class that has a 
    //   "ReleaseResources" method (assuming all
    //   classes are ultimately derived from Object.
    obj.ReleaseResources
}

main() {

    DatabaseConnection dbConn;
    FileHandle fh;

    // You can pass in anything at all and it will
    //   compile just fine. But if you pass in an
    //   object that doesn't have a "ReleaseResources"
    //   method you'll get a run-time error.
    FreeMemory(dbConn);
    FreeMemory(fh);
    FreeMemory(acct); //FAIL! (but not until run-time)
}

For an excellent example, look at the .NET ToString() method. All classes have it because all classes are derived from the Object class. But each class can implement ToString() in a way that makes sense for itself.

EDIT: Simple != short, IMHO

Pairoar answered 17/10, 2008 at 3:29 Comment(0)
G
1

Polymorphism is dividing the world into boxes based on common properties and treating the items in a given box as interchangeable when you only want to use these common properties.

Greenshank answered 22/10, 2008 at 23:7 Comment(0)
S
1

Polymorphism is the ability to treat different things as if they were the same thing by establishing a shared identity between them then exploiting it.

Sigismundo answered 5/11, 2008 at 23:11 Comment(1)
Right. This is also why they use profiling in airport security... which is another type of generalizing...Surbeck
E
1

Polymorphism is language functionality allowing high-level algorithmic code to operate unchanged on multiple types of data.

This is done by ensuring the operations invoke the right implementation for each data type. Even in an OOP context (as per this question's tag), this "right implementation" may be resolved at compile-time or run-time (if your language supports both). In some languages like C++, compiler-supplied support for run-time polymorphism (i.e. virtual dispatch) is specific to OOP, whereas other types of polymorphism can also operate on data types that aren't objects (i.e. not struct or class instances, but may be builtin types like int or double).

( The types of polymorphism C++ supports are listed and contrasted in my answer: Polymorphism in c++ - even if you program other languages, it's potentially instructive )

Electorate answered 16/6, 2011 at 6:23 Comment(0)
J
0

The way I try and think of it is something that looks the same but can have different functionality depending on the instance. So you can have a type

interface IJobLoader

but depending on how it is used can have different functionality while still looking the same. You may have instances for BatchJobLoader, NightlyJobLoader etc

Maybe I am way off.

Jp answered 16/10, 2008 at 22:4 Comment(0)
C
0

The term polymorphism can also apply to overloading functions. For example,

string MyFunc(ClassA anA);
string MyFunc(ClassB aB);

is a non-object oriented example of polymorphism.

Cohabit answered 17/10, 2008 at 1:38 Comment(0)
D
0

It is a way to treat different things that can do something something similar in the same way without caring how they do it.

Let's say you have a game with a bunch of different types of Vehicles driving around such as Car, Truck, Skateboard, Airplane, etc... They all can Stop, but each Vehicle stops in a different way. Some Vehicles may need to shift down gears, and some may be able to come to a cold stop. Polymophism lets you do this

foreach (Vehicle v in Game.Vehicles)
{
   v.Stop();
}

The way that stop is implemented is deferred to the different Vehicles so your program doesn't have to care about it.

Dogvane answered 17/10, 2008 at 1:44 Comment(0)
L
0

Is the ability that objects have to respond to the same message in different ways.

For instance , in languages such as smalltalk, Ruby, Objective-C, you just have to send the message and they will respond.

 dao  = XmlDao.createNewInstance()    #obj 1
 dao.save( data )

 dao = RdbDao.createNewnewInstance()  #obj 2
 dao.save( data )

In this example two different objects, responded in different ways to the same messages: "createNewInstance() and save( obj )"

They act in different ways, to the same message. In the above languages, the classes might not even be in the same class hierarchy, it is enough that they respond to the message.

In languages such as Java, C++, C# etc. In order to assign the object to an object reference, they must share the same type hierarchy either by implementing the interface or by being subclass of a common class.

easy .. and simple.

Polymorphism is by far, the most important and relevant feature of object oriented programming.

Lanielanier answered 17/10, 2008 at 2:1 Comment(0)
J
0

It's just a way to get old cold to call new code. You write some application that accepts some "Shape" interface with methods that others must implement (example - getArea). If someone comes up with a new whiz-bang way to implement that interface your old code can call that new code via the the getArea method.

Jesicajeske answered 17/10, 2008 at 3:48 Comment(0)
P
0

The ability of an object of some type (e.g. a car) to act (e.g. brake) like one of another type (e.g. a vehicle) which usually suggests common ancestry (e.g. car is a subtype of vehicle) at one point in the type hierarchy.

Parachronism answered 22/10, 2008 at 23:14 Comment(0)
F
-3

Polymorphism is the Object Oriented solution to problem of passing a function to another function. In C you can do

 void h() { float x=3.0; printf("%f", x); }
 void k() { int y=5; printf("%i", y); }
 void g(void (*f)()) { f(); }
 g(h);  // output 3.0
 g(k);  // output 5

In C things get complicated if the function depends on additional parameters. If the functions h and k depend on different types of parameters you are in trouble and you must use casting. You have to store those parameters in a data structure, and pass a pointer to that data structure to g which passes it to h or k. h and k cast the pointer into a pointer to the proper structure and unpack the data. Very messy and very unsafe because of possible casting errors:

 void h(void *a) { float* x=(float*)a; printf("%f",*x); }
 void k(void *a) { int* y=(int*)a; printf("%i",*y); }
 void g(void (*f)(void *a),void *a) { f(a); }
 float x=3.0;
 int y=5;
 g(h,&x); // output x
 g(k,&y); // output y

So they invented polymorphism. h and k are promoted to classes and the actual functions to methods, the parameters are member variables of the respective class, h or k. Instead of passing the function around, you pass an instance of the class that contains the function you want. The instance contains its own parameters.

class Base { virtual public void call()=0; }
class H : public Base { float x; public void call() { printf("%f",x);} } h;
class K : public Base { int y; public void call() { printf("%i",y);} } k;
void g(Base &f) { f.call(); };
h.x=3.0;
k.y=5;
g(h); // output h.x
g(k); // output k.x
Feliciafeliciano answered 17/10, 2008 at 4:21 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.