Overriding a superclass property with a different type in Swift


We can define a subclass that is inherited from a superclass in the Swift language, That means you can override its properties and methods using the override keyword.

However, you cannot override the properties with a different type in the subclass. By default, the subclass must override the properties of the same type as the superclass type.

For example, let's say you have a Person class with name and age properties of type String and Double −

class Person {
   let name: String
   let age: Double
    
   init(name: String, age: Double) {
      self.name = name
      self.age = age
   }
}

Now, let's say you have a subclass called Student that inherits from Person, and you want to override the age property to be of type Int instead −

class Student: Person {
   let grade: Int
   override var age: Int {
      return age
   }
}

This code will produce a compile-time error because the type of the age property in the Student subclass is different from the type of the age property in the Person superclass. The error looks like this −

error: property 'age' with type 'Int' cannot override a property with type 'Double'

Here are some examples of overriding superclass properties with different types in Swift −

Example 1: Overriding a superclass property with a subtype

Step 1 − In this example, the Dog class overrides the name property of the Animal class with the same type (String).

Step 2 − However, it also adds a didSet observer that prints "Dark!" whenever the name property is set.

Step 3 − This is an example of how you can add functionality to an inherited property while still keeping the same type.

import Foundation
class Animal {
   var name: String
    
   init(name: String) {
      self.name = name
   }
}
class Dog: Animal {
   override var name: String {
      didSet {
         print("Bark!")
      }
   }
}
let dog = Dog(name: "Tommy")
dog.name = "Harry"

Output

Bark!

Example 2: Overriding a superclass Property with a Computed Property

import Foundation
class Shape {
   var area: Double {
      fatalError("Subclasses must override this property")
   }
}
class Rectangle: Shape {
   var width: Double
   var height: Double
    
   init(width: Double, height: Double) {
      self.width = width
      self.height = height
   }
    
   override var area: Double {
      return width * height
   }
}
let rectangle = Rectangle(width: 10.0, height: 20.0)
print(rectangle.area)

Output

200.0

In this example, the Shape class defines a read-only property named area that, if it is not overridden by a subclass, results in a fatal error. The area property of a rectangle is replaced by a computed property by the Rectangle class, which determines the area of a rectangle using the width and height values. This is an illustration of how you may define an inherited property that behaves differently in each subclass using a calculated property.

Example 3: Overriding a Superclass Property with an Extra Variable in the Subclass

import Foundation
class Person {
   let name: String
   let age: Double
    
   init(name: String, age: Double) {
      self.name = name
      self.age = age
   }
}
class Student: Person {
   var grade: Int
    
   init(grade: Int) {
      self.grade = grade
      super.init(name: "", age: 0.0)
   }
}
class School {
   var person = Person(name: "", age: 0.0)
}
class PrimarySchool: School {
   var student = Student(grade: 8)
   override var person: Person {
      get {
         return student
      } set {
         if let newStudent = newValue as? Student {
            student = newStudent
         } else {
            print("Incorrect student type for primary school.")
         }
      }
   }
}

It seems one cannot declare a property with the let syntax and override it with var in its subclass or vice-versa, which may be because the superclass implementation might not be expecting that property to change once initialized.

So in this case the property needs to be declared with ‘var’ in the superclass as well to match the subclass (as shown in the snippet above). If one cannot change the source code in the superclass then its probably best to destroy the current RaceCar and create a new PrimarySchool every time the person needs to be mutated.

Conclusion

Swift provides you with the flexibility to orderride the properties and methods in the subclasses. Also, you can override the property of a superclass with a different type in subclasses.

For this, you can use the computed property instead of the stored property if you want to change the actual type of a property from the superclass. Using the computed properties, you can override the getter and setter with the different types.

Updated on: 11-Apr-2023

934 Views

Kickstart Your Career

Get certified by completing the course

Get Started
Advertisements