Polymorphism is a Greek word that means "many forms".
In programming, it describes the ability of a single interface or function to operate on multiple different data types.
In Swift, polymorphism allows you to treat objects of different subclasses as if they were objects of their shared superclass.
Let's say we have a base class Animal and two subclasses Dog and Cat.
Both Dog and Cat override a method called makeSound().
Because of polymorphism, we can create an array of Animal objects, put both Dogs and Cats inside it, and call makeSound() on all of them seamlessly.
class Animal {
func makeSound() { print("Some generic sound") }
}
class Dog: Animal {
override func makeSound() { print("Bark!") }
}
class Cat: Animal {
override func makeSound() { print("Meow!") }
}
// An array typed as [Animal]
let pets: [Animal] = [Dog(), Cat(), Animal()]
for pet in pets {
// Swift dynamically calls the correct overridden method at runtime
pet.makeSound()
}
How does the compiler know whether to print "Bark" or "Meow" when iterating over the Animal array?
This happens through a process called Dynamic Dispatch.
At runtime, Swift looks at the actual type of the object stored in memory, rather than the type of the variable holding it.
Even though the loop variable pet is typed as Animal, Swift sees that the actual object is a Dog and triggers the dog's version of the method.
There is another type of polymorphism called Method Overloading.
This occurs when you have multiple functions with the exact same name, but different parameter types or parameter counts.
func printValue(_ value: Int) {
print("Integer: \(value)")
}
func printValue(_ value: String) {
print("String: \(value)")
}
printValue(42) // Calls the Int version
printValue("Hello") // Calls the String version
The compiler decides which function to execute at compile time based on the arguments provided.
When a subclass is treated as its superclass but executes its own overridden methods, what concept is being demonstrated?