Polymorphism is the practice of using one object of one particular class as if it were another object of another class. Let's take a look at how this is done in Python. This is actually something that Python is very good at. We'll make a working copy of classes.py and we'll call it classes-working.py. We'll open that and we see we have our Duck class that has quack and walk in it. And we'll go ahead and create a Dog class and Dog will have bark.
And fur. The dog has brown and white fur. Now, we'll go ahead and create a dog object called fido = Dog and fido.bark and fido.fur. So now we have a Dog object and a Duck object.
And if we go and run this, we see that the Duck quacks and walks like a duck. And the Dog barks and has brown and white fur. So these are two separate and distinct objects and they have two separate and distinct interfaces. If we want to be able to use them polymorphically, we need to make sure that they have a common interface. And so the Duck class, we can give it a bark and a fur and say bark.
print('The duck cannot bark'). And fur, and this one will say "The duck has feathers." And we can give the Dog, a walk. print('Walks like a dog'). And quack. The dog cannot quack.
Now, we can use them in the same way. For example, let's just get rid of all of this, and we have a Dog and we have a Duck. And if I say for object in and give it a list, donald and fido. I can say, o.quack(), o.walk(), o.bark(), o.fur().
So what we have here is we're calling all four of these functions for both of these objects. We're using them in exactly the same way. We're using them in a way that really does not know or care exactly what type of an object it is. It's simply calling these methods without concern for which type of an object, just assuming that these methods actually exist in there. So we'll save that and we'll run it and we see our result. We have the Duck first. Quaaack! Walks like a duck. The duck cannot bark. The duck has feathers.
And then we have the Dog. And there is all those same methods on the Dog. So if I had say a function, say in_the_ forest, and it expects a dog and it says, dog.bark() and dog.fur(). And let's say I had another one that says in_the_pond and it expects a duck.
And it says duck.quack() and it calls duck.walk(). Now, I can call either of these methods with either of these objects. I can say in_the_forest, and you see the in_the_forest is expecting a dog and I can pass it donald. And as long as donald implements the interface that is being used in this function, it will still work. Save this and run it. It says the duck cannot bark and The duck has feathers.
And likewise, if I call in_the_pond and I pass it fido, save that and run it. The dog cannot quack and it walks like a dog. So this is what polymorphism is. And Python is particularly good at this because the objects in Python don't actually care what the name of the class is. When you use an object, Python is what's called loosely typed or actually they call it duck typing, because the types in Python, everything is an object.
And if it walks like a duck, then you can use it like a duck. That's why they call it duck typing. It's loosely typed. When I declare that this in_the_forest function expects a dog, I'm just naming it dog, but it's an object. I could name it cat and it would still work exactly the same, because that's really just a variable name. That's not a type name at all. That's no kind of a restriction. It's just what I'm calling it here. So I save that and run it. It still works exactly the same.
So a strong advantage of this loosely typed or what they call duck typing is that polymorphism is natural. So I can create a super class that implements all of the things that an animal normally does, and then I can create subclasses from that with just the specific attributes of the type of an animal that I'm interfacing, and then anything that expects any of those interfaces can use it. Because all of those interfaces are guaranteed to be there.
So I know that that's a big concept to wrap your head around, but think of it this way. Any object of any class that implements the interface that's expected by any function can be used by that function. So when I create a function here called in_the_forest and it expects an object that can bark and an object that has fur, or a function that expects an object that can quack and the object that can walk, any object that implements those methods will work in that function regardless of what its type is.
And that is polymorphism and that's how it works in Python.
Get unlimited access to all courses for just $25/month.Become a member