Swift - Overriding



Overriding is a very common concept in object-oriented programming languages. Using overriding we are allowed to re-implement a method or property of a superclass in a subclass. It allows us to extend the behaviour of inheritance. While overriding the method or property we are providing a new implementation in the subclass instead of using the the implementation in the superclass. In Swift, we can override the method or the property of the superclass.

Access to Superclass Methods, Properties and Subscripts

The 'super' keyword is used as a prefix to access the methods, properties and subscripts declared in the superclass.

Overriding Access to methods, properties and subscripts
Methods super.somemethod()
Properties super.someProperty()
Subscripts super[someIndex]

Rules for overriding in Swift

Following are some rules you should follow while overriding −

  • The overridden method or property in the subclass must have the same signature(name, parameter and return type) as they are in the superclass.

  • Use the super keyword to call the overridden implementation from the superclass in the overriding method.

  • Use the override keyword to override properties. We can override both stored and computed properties.

  • The access level of an overriding method or property cannot be more restrictive than the access level of the overridden method or property in the base class. You are not allowed to override a public method with a private method. So always check the access modifier before overriding.

Methods Overriding in Swift

In Swift, we are allowed to override methods. The overriding method means a subclass can provide a different implementation for a method that is already defined in the base class. Or we can say that we can customize the behaviour of a superclass method in the subclass.

The overridden method in the subclass must have the same signature(name, parameter and return type) as the base class and the compiler will determine which method is called according to the type of object. Also, the access level of the overridden method in the subclass must be the same or more permissive than the access level of the method in the superclass.

The override method is defined by using the override keyword in the subclass. This keyword is placed before starting the function definition. It tells the compiler that the method will override the method of the superclass. If we do not specify the override keyword then the compiler will give us the error.

Syntax

Following is the syntax for method overriding −

override func methodName(Parameters) -> returntype {
   Statement
   return parameters
}

Example

Swift program for method overriding.

// Super class
class cricket {
   // Method
   func show() {
      print("Welcome to Swift Super Class")
   }
}

// Sub class
class tennis: cricket {
   // Overriden Method
   override func show() {
      print("Welcome to Swift Sub Class")
   }
}

// Creating instance of subclass
let tennisinstance = tennis()

// Accessing the override method
tennisinstance.show()

Output

It will produce the following output −

Welcome to Swift Sub Class

Property Overriding

Swift supports property overriding. Just like method overriding, property overriding also provides a way for a subclass to customize the implementation of the properties that are already defined in the base class. We can say that using property overriding, we can provide our own getter and setter for that property or add property observers, which enables the overriding property to observe when the property value changes.

The type of the overridden property in the subclass must have the same name and type as the property in the base class. So that the compiler will determine which property(either the superclass property or overridden property) is called according to the type of object. The access level of the overridden method in the subclass must be similar or more permissive than the access level of the property in the superclass.

The override property is defined by using the override keyword in the subclass. This keyword is placed before starting the property definition. It tells the compiler that the property will override the property of the superclass. If we do not specify the override keyword, then the compiler will give us the error.

Syntax

Following is the syntax for property overriding −

override var propertyName: type{
   // Statement
}

Example

Swift program for property overriding.

// Superclass
class mySuperClass {

   // Property
   var language: String{
      return "C++"
   }
}
// Subclass
class mySubClass: mySuperClass {

   // Override Property
   override var language: String{
      return "Swift"
   }
}

// Creating an instance of a subclass
let obj = mySubClass()

// Accessing the overridden property
print(obj.language)

Output

It will produce the following output −

Swift

Overriding Property Getters and Setters

Swift allows the user to override the getter and setter of the subclass property, whether the property is stored or computed. The name and the type of the overriding property must be the same as the property present in the base case. So that the compiler knows that you are overriding the property of the base class.

In Swift, we are allowed to represent the read-only inherited property as a read-write property by providing both a getter and setter in the subclass while overriding. Whereas we are not allowed to represent the read-write-only inherited property as read-only property. When setter is defined for overriding property the user has to define getter too. If we do not wish to modify the value of the inherited property in the overriding getter, then we can pass the inherited value using 'super.PropertyName' from the getter, where PropertyName represents the name of the overriding property.

Example

Swift program for overriding property getter and setter.

// Base Class
class Circle {
   var radius = 12.5
    
   // Property with getter
   var area: String {
      return "of rectangle for \(radius) "
   }
}

// Subclass
class Rectangle: Circle {
   var print = 7
    
   // Overriding the getter
   override var area: String {
      return super.area + " is now overridden as \(print)"
   }
}

// Creating instance
let rect = Rectangle()

// Accessing the properties
rect.radius = 25.0
rect.print = 3
print("Radius \(rect.area)")

Output

It will produce the following output −

Radius of rectangle for 25.0  is now overridden as 3

Overriding Property Observers

When a new property needs to be added for an inherited property, 'property overriding' concept is introduced in Swift 4. This notifies the user when the inherited property value is altered. But overriding is not applicable for inherited constant stored properties and inherited read-only computed properties.

Example

class Circle {
   var radius = 12.5
   var area: String {
      return "of rectangle for \(radius) "
   }
}

class Rectangle: Circle {
   var print = 7
   override var area: String {
      return super.area + " is now overridden as \(print)"
   }
}

let rect = Rectangle()
rect.radius = 25.0
rect.print = 3
print("Radius \(rect.area)")

class Square: Rectangle {
   override var radius: Double {
      didSet {
         print = Int(radius/5.0)+1
      }
   }
}

let sq = Square()
sq.radius = 100.0
print("Radius \(sq.area)")

Output

When we run the above program using playground, we get the following result −

Radius of rectangle for 25.0  is now overridden as 3
Radius of rectangle for 100.0  is now overridden as 21

Preventing Overriding in Swift

Swift provides a special keyword to prevent methods, properties, subscripts, or even classes from being overridden and this keyword is known as the final keyword. The final keyword explicitly indicates that the specified method, property, subscript or class can not be overridden by the subclasses. If the user still tries to attempt overriding, then the compiler will give errors.

The final keyword is always used before the declaration of the method, property, subscript or class.

Syntax

Following is the syntax for preventing overriding −

// For methods
final func methodName(Parameters) -> returntype{}

// For property
final var propertyName : type

// For subscript
final subscript(index: Int)->Elemnt{}

// For class
final class className{}

Example

Swift program to prevent overriding.

// Base class
final class Circle {
   final var radius = 12.5
   var area: String {
      return "of rectangle for \(radius) "
   }
}

// Sub class
class Rectangle: Circle {
   var print = 7
   override var area: String {
      return super.area + " is now overridden as \(print)"
   }
}

// Creating instance
let rect = Rectangle()
rect.radius = 25.0
rect.print = 3
print("Radius \(rect.area)")

Error

main.swift:12:17: error: property overrides a 'final' property
   override var area: String {
                ^
main.swift:4:8: note: overridden declaration is here
   var area: String {
       ^
main.swift:10:7: error: inheritance from a final class 'Circle'
class Rectangle: Circle {
      ^
main.swift:21:17: error: ambiguous use of 'area'
print("Radius \(rect.area)")
                ^
main.swift:12:17: note: found this candidate
   override var area: String {
                ^
main.swift:4:8: note: found this candidate
   var area: String {
       ^

Since the superclass is declared as 'final' and its data types are also declared as 'final' the program won't allow to create subclasses further and it will throw errors.

Advertisements