Swift Inheritance (original) (raw)

Last Updated : 23 Jul, 2025

Inheritance is one of the fundamental concepts of object-oriented programming (OOP) languages. It allows us to create a new class from an existing class and reuse the existing code and functionality. In this article, we will learn about inheritance in Swift and how to use it to create subclasses, override methods and properties, and implement polymorphism.

What is Inheritance?

Inheritance is a relationship between two classes, where one class inherits the methods, properties, and other characteristics from another class.

Below is a Swift program to implement inheritance:

Swift `

// Swift program to implement // Inheritance // Define a superclass class Animal {
// Property in the superclass var species: String = ""

// Method in the superclass func speak() { print("An animal of species (species) is making a sound.") } }

// Define a subclass that inherits from Animal class Dog: Animal { // Additional properties and methods in the subclass var breed: String = ""

func wagTail() { print("The dog of breed (breed) is wagging its tail.") } }

// Create an instance of Dog let myDog = Dog()

// Set values for properties myDog.species = "Canine" myDog.breed = "Golden Retriever"

// Access methods and properties // An animal of species Canine is making a sound. myDog.speak()

// The dog of breed Golden Retriever is wagging its tail. myDog.wagTail()

`

**Output:

An animal of species Canine is making a sound.
The dog of breed Golden Retriever is wagging its tail.

Explanation:

How to Override Methods and Properties?

Sometimes, we may want to modify or extend the behavior of a method or a property that is inherited from a superclass.

Below is Swift program to override methods and properties:

Swift `

// Swift program to override methods // and properties // Define a superclass class Animal { // Properties and methods of the superclass var name: String = ""

var description: String { return "I am an animal named (name)" }

func makeNoise() { print("I can make noise") } }

// Define a subclass that inherits from Animal class Dog: Animal { // Override the computed property override var description: String { return "I am a dog named (name)" }

// Override the method override func makeNoise() { print("I can bark") } }

// Create an instance of Dog let dog = Dog()

// Assign a name to the dog dog.name = "Rex"

// Access the overridden computed property // I am a dog named Rex print(dog.description)

// Call the overridden method // I can bark dog.makeNoise()

// Define a subclass that inherits from Dog class Labrador: Dog { // Override the computed property again override var description: String { return "I am a labrador named (name), (super.description)" } }

// Create an instance of Labrador let lab = Labrador()

// Assign a name to the labrador lab.name = "Max"

// Access the overridden computed property // I am a labrador named Max, I am a dog named Max print(lab.description)

// Call the inherited method // I can bark lab.makeNoise()

`

**Output:

I am a dog named Rex
I can bark
I am a labrador named Max, I am a dog named Max
I can bark

**Explanation:

Types of Inheritance

Swift supports different types of inheritance, depending on the relationship between the classes involved. Some of the common types of inheritance are:

1. Single inheritance

A subclass inherits from only one superclass. This is the most common type of inheritance in Swift. For example:

class Vehicle
{
// properties and methods of Vehicle
}
class Car: Vehicle
{
// properties and methods of Car
}

Here, the **Car class inherits from the **Vehicle class, which means that a **Car instance can access the properties and methods of the **Vehicle class, as well as its properties and methods.

2. Multilevel inheritance

A subclass inherits from another subclass, which in turn inherits from a superclass. This creates a chain of inheritance from the top-level superclass to the bottom-level subclass. For example:

class Vehicle
{
// properties and methods of Vehicle
}
class Car: Vehicle
{
// properties and methods of Car
}
class ElectricCar: Car
{
// properties and methods of ElectricCar
}

Here, the **ElectricCar class inherits from the **Car class, which in turn inherits from the **Vehicle class. This means that an **ElectricCar instance can access the properties and methods of all three classes in the hierarchy.

3. Multiple inheritance

A subclass inherits from more than one superclass. This allows a subclass to combine the features and behaviors of multiple superclasses. However, Swift does not support multiple inheritance for classes directly. Instead, Swift uses protocols to achieve a similar effect. A protocol defines a set of requirements that a conforming type must implement, such as properties, methods or subscripts. A class can conform to multiple protocols by listing them after the colon: in its declaration. For example:

protocol Flyable
{
// requirements for flying
}
protocol Swimable
{
// requirements for swimming
}
class Duck: Animal, Flyable, Swimable
{
// properties and methods of Duck
}

Here, the **Duck class inherits from the Animal class and also conforms to the **Flyable and **Swimable protocols. This means that a **Duck instance can access the properties and methods of the **Animal class, as well as the requirements of the two protocols.

Is-a Relationship

In Swift, inheritance is an is-a relationship. That is, we use inheritance only if there exists an is-a relationship between two classes. An is-a relationship means that a subclass is a specific type or kind of its superclass. For example:

Here, we can use inheritance to model these relationships by creating subclasses for each specific type or kind.

Swift `

// Swift program to implement // is-a relationship // Define a base class for vehicles class Vehicle { var brand: String var year: Int

// Initialize the vehicle with a brand and year init(brand: String, year: Int) { self.brand = brand self.year = year }

// Method to start the vehicle's engine func startEngine() { print("The (brand) vehicle's engine is starting.") } }

// Create a subclass for cars class Car: Vehicle { var model: String

// Initialize the car with a brand, year, and model init(brand: String, year: Int, model: String) { self.model = model super.init(brand: brand, year: year) }

// Method to drive the car func drive() { print("The (year) (brand) (model) is driving.") } }

// Define a base class for fruits class Fruit { var name: String

// Initialize the fruit with a name init(name: String) { self.name = name }

// Method to describe the fruit func describe() { print("This is a (name).") } }

// Create a subclass for apples class Apple: Fruit { var variety: String

// Initialize the apple with a name and variety init(name: String, variety: String) { self.variety = variety super.init(name: name) }

// Method to describe the taste of the apple func taste() { print("This (name) is a (variety) apple, and it tastes delicious.") } }

// Define a base class for animals class Animal { var species: String

// Initialize the animal with a species init(species: String) { self.species = species }

// Method to make a sound func makeSound() { print("The (species) is making a sound.") } }

// Create a subclass for cats class Cat: Animal { var name: String

// Initialize the cat with a name init(name: String) { self.name = name super.init(species: "Cat") }

// Method for a cat to meow func meow() { print("(name) the cat says 'Meow!'") } }

// Creating and using objects let myCar = Car(brand: "Toyota", year: 2023, model: "Camry") myCar.startEngine() myCar.drive()

let myApple = Apple(name: "Apple", variety: "Honeycrisp") myApple.describe() myApple.taste()

let myCat = Cat(name: "Whiskers") myCat.makeSound() myCat.meow()

`

**Output:

The Toyota vehicle's engine is starting.
The 2023 Toyota Camry is driving.
This is a Apple.
This Apple is a Honeycrisp apple, and it tastes delicious.
The Cat is making a sound.
Whiskers the cat says 'Meow!'

Using inheritance to express an is-a relationship helps us to reuse code, avoid duplication and maintain consistency across related classes.

Method Overriding

A subclass can provide its custom implementation of an instance method, type method, instance property, type property or subscript that it would otherwise inherit from a superclass. This is known as overriding. To override a characteristic that would otherwise be inherited, we prefix our overriding definition with the override keyword.

Below is the Swift program to implement method overriding:

Swift `

// Swift program to implement // method overriding

// Define a base class for animals class Animal { // Method in the superclass func eat() { print("I can eat") } }

// Create a subclass for dogs, // which inherits from Animal class Dog: Animal { // Override the eat() method in the subclass override func eat() { print("I eat dog food") } }

// Creating and using objects let genericAnimal = Animal() let myDog = Dog()

genericAnimal.eat() myDog.eat()

`

**Output

I can eat
I eat dog food

**Explanation:

Overriding allows us to customize and modify the behavior of inherited methods, properties or subscripts according to the needs of the subclass.

super Keyword

In Swift, we can access methods, properties or subscripts of the superclass from a subclass using the **super keyword. The **super keyword refers to the superclass instance within the current subclass instance. This allows us to invoke the superclass's implementation of a method or access its properties.

Below is the Swift program to implement super keyword:

Swift `

// Swift program to implement // super keyword

// Define a base class for animals class Animal { // Method in the superclass func eat() { print("I can eat") } }

// Create a subclass for dogs, // which inherits from Animal class Dog: Animal { // Override the eat() method in the subclass override func eat() { // Call the eat() method of the superclass super.eat()

// Add additional behavior
print("I eat dog food")

} }

// Create an object of the subclass // (a Labrador dog) var labrador = Dog()

// Call the eat() method on the // Labrador object labrador.eat()

`

**Output

I can eat
I eat dog food

**Explanation:

Using super enables us to access and utilize inherited characteristics of the superclass from within the subclass, allowing for the customization of behavior while preserving and extending the functionality of the parent class.

Property Overriding

A subclass can also override inherited properties of a superclass by providing its custom getter and setter for the properties or adding property observers to them. Property observers are code blocks that are executed when a property’s value is set or changed. There are two types of property observers: **willSet and **didSet. The **willSet observer is called before the value of a property is stored and the **didSet observer is called after the value of a property is stored.

To override a property, we use the same syntax as for overriding a method, but we also specify what aspect of the property we want to override: its getter, its setter or its observers.

**Example 1: Below is the Swift program to implement property overriding:

Swift `

// Swift program to implement // property overriding

// Define a base class for vehicles class Vehicle { // Property in the superclass to represent // the current speed in miles per hour (mph) var currentSpeed = 0.0 }

// Create a subclass for cars, which // inherits from Vehicle class Car: Vehicle { // Override the property with a custom getter // and setter to convert speed to kilometers // per hour (kph) override var currentSpeed: Double { get { // Custom getter to convert mph to kph // Convert mph to kph return super.currentSpeed * 1.6 } set { // Custom setter to convert kph back to mph // Convert kph to mph super.currentSpeed = newValue / 1.6 } } }

// Create an instance of the Car class let myCar = Car()

// Set the current speed in miles per hour (mph) // Set the speed to 60 mph myCar.currentSpeed = 60.0

// Retrieve and print the current speed in // kilometers per hour (kph) let speedInKPH = myCar.currentSpeed print("Current speed: (speedInKPH) kph")

`

**Output

Current speed: 60.0 kph

**Explanation:

**Example 2:

Swift `

// Swift program to implement // Property overriding

// Define a base class for vehicles class Vehicle { // Computed property in the superclass // to describe the vehicle's speed var description: String { return "traveling at (currentSpeed) miles per hour" }

// Property to represent the current speed // in miles per hour (mph) var currentSpeed = 0.0 }

// Create a subclass for cars, which inherits // from Vehicle class Car: Vehicle { // Override the description property with a custom // getter to include "in a car" override var description: String { return super.description + " in a car" } }

// Create an instance of the Car class let myCar = Car()

// Set the speed to 60 mph myCar.currentSpeed = 60.0

// Access and print the description property let carDescription = myCar.description print(carDescription)

`

**Output

traveling at 60.0 miles per hour in a car

**Explanation:

**Example 3:

Swift `

// Swift program to implement // Property overriding

// Define a base class for vehicles class Vehicle { // Property in the superclass with a // didSet observer var currentSpeed = 0.0 { didSet { print("The speed changed to (currentSpeed)") } } }

// Create a subclass for cars, which inherits // from Vehicle class Car: Vehicle { // Override the property with custom willSet // and didSet observers override var currentSpeed: Double { willSet { print("The speed will change to (newValue)") } didSet { print("The speed changed by (currentSpeed - oldValue)") } } }

// Create an instance of the Car class let myCar = Car()

// Set the current speed, triggering willSet // and didSet observers myCar.currentSpeed = 60.0

// Set the speed again to observe changes myCar.currentSpeed = 80.0

`

**Output

The speed will change to 60.0
The speed changed to 60.0
The speed changed by 60.0
The speed will change to 80.0
The speed changed to 80.0
The speed changed by 20.0

**Explanation:

Overriding properties allows us to customize and modify how inherited properties are accessed or observed according to the needs of the subclass.

Final Property

Swift allows us to prevent a subclass from overriding a method, property, or subscript of a superclass by using the final modifier. We write the final keyword before the declaration of the characteristic that we want to protect from overriding (such as final var, final func, final class func and final subscript). If a subclass tries to override a final characteristic, it will cause a compile-time error.

Below is the Swift program to implement Final property:

Swift `

// Swift program to implement // Final

// Define a base class for vehicles class Vehicle { // Mark the property as final to prevent // overriding in subclasses final var currentSpeed = 0.0 }

// Create a subclass for cars, which // inherits from Vehicle class Car: Vehicle { // Attempt to override the final property // (this will cause an error) // Uncomment the following lines to see the error:

/* override var currentSpeed: Double { // This will result in a compilation error } */ }

// Attempting to create instances and override // the final property will result in an error

// Uncomment these lines to observe the error: /* let myVehicle = Vehicle() myVehicle.currentSpeed = 60.0 // Error: Cannot assign to property: 'currentSpeed' is a 'final' property

let myCar = Car() myCar.currentSpeed = 80.0 // Error: Cannot assign to property: 'currentSpeed' is a 'final' property */

`

**Explanation:

Using the final modifier helps us ensure that a superclass characteristic's behavior and functionality are consistent and reliable across all subclasses.

Conclusion

In this article, we have learned about inheritance in Swift and how to use it to create subclasses, override methods and properties, and implement polymorphism. Inheritance is a powerful feature of object-oriented programming that allows us to reuse and extend existing code and functionality. It also helps us to model real-world objects and relationships in our programs. We have also seen some of the types of inheritance and the is-a relationship that exists between classes. We have also learned how to use the super keyword to access the superclass characteristics from the subclass and how to use the final keyword to prevent overriding. We hope this article has helped you to understand the concept of inheritance in Swift better.