Polymorphism in Swift
In Swift, polymorphism is an essential feature of Object-Oriented
Programming that allows objects of different classes to be treated
as objects of a common superclass. It enables methods to perform
differently based on the object calling them, even if they share the
same interface.
Polymorphism in Swift is mainly achieved through method overriding
and protocol conformance, allowing flexibility and dynamic method
resolution at runtime. This helps in writing generic and reusable
code.
Key Points to Remember
- Polymorphism allows a single function, method, or operator to behave differently for different types of input.
- It enables method overriding in subclasses to provide specific implementations of methods defined in the superclass.
- Protocol-based polymorphism allows unrelated classes to share a common behavior by conforming to the same protocol.
- Polymorphism supports dynamic dispatch, where the method that gets executed is determined at runtime based on the object type.
- Helps achieve loose coupling and code reusability.
Syntax
class Superclass {
func methodName() {
// Superclass implementation
}
}
class Subclass: Superclass {
override func methodName() {
// Subclass-specific implementation
}
}
let object: Superclass = Subclass()
object.methodName()
// Calls overridden method in Subclass
Example 1: Method Overriding for Polymorphism
Let's demonstrate how method overriding allows polymorphic behavior in Swift.
import Foundation
class Shape {
func area() {
print("Calculating area of shape")
}
}
class Circle: Shape {
override func area() {
print("Area of circle: πr²")
}
}
class Rectangle: Shape {
override func area() {
print("Area of rectangle: length × width")
}
}
let shapes: [Shape] = [Circle(), Rectangle()]
for shape in shapes {
shape.area()
}
Output
Area of rectangle: length × width
Example 2: Polymorphism Using Protocols
Protocols enable polymorphism without inheritance by defining common behaviors for unrelated types.
import Foundation
protocol Drawable {
func draw()
}
class Triangle: Drawable {
func draw() {
print("Drawing a triangle")
}
}
class Square: Drawable {
func draw() {
print("Drawing a square")
}
}
let drawables: [Drawable] = [Triangle(), Square()]
for drawable in drawables {
drawable.draw()
}
Output
Drawing a square
Example 3: Polymorphism with Class Hierarchies and Method Overriding
Here’s another example showing how polymorphism works with a real-world analogy of employees.
import Foundation
class Employee {
func work() {
print("Employee is working")
}
}
class Manager: Employee {
override func work() {
print("Manager is managing the team")
}
}
class Developer: Employee {
override func work() {
print("Developer is writing code")
}
}
let employees: [Employee] = [Manager(), Developer(), Employee()]
for employee in employees {
employee.work()
}
Output
Developer is writing code
Employee is working
Example 4: Function Accepting Superclass Type Demonstrating Polymorphism
A function that takes a superclass type can accept any subclass object, showcasing polymorphism.
import Foundation
class Animal {
func makeSound() {
print("Some generic animal sound")
}
}
class Cat: Animal {
override func makeSound() {
print("Meow")
}
}
class Dog: Animal {
override func makeSound() {
print("Bark")
}
}
func animalSound(animal: Animal) {
animal.makeSound()
}
let myCat = Cat()
let myDog = Dog()
animalSound(animal: myCat)
// Output: Meow
animalSound(animal: myDog)
// Output: Bark
Output
Bark