Swift Inheritance
Inheritance can be understood as a class acquiring the methods and properties of another class.
When a class inherits from another class, the inheriting class is called the subclass, and the class being inherited from is called the superclass (or parent class).
In Swift, a class can call and access the methods, properties, and subscript scripts of its superclass and can override them.
We can also add property observers to inherited properties in a class.
Base Class
A class that does not inherit from any other class is called a base class (Base Class).
In the following example, we define a base class StudDetails
that describes a student (stname) and their scores in various subjects (mark1, mark2, mark3):
class StudDetails {
var stname: String!
var mark1: Int!
var mark2: Int!
var mark3: Int!
init(stname: String, mark1: Int, mark2: Int, mark3: Int) {
self.stname = stname
self.mark1 = mark1
self.mark2 = mark2
self.mark3 = mark3
}
}
let stname = "swift"
let mark1 = 98
let mark2 = 89
let mark3 = 76
let sds = StudDetails(stname:stname, mark1:mark1, mark2:mark2, mark3:mark3)
print(sds.stname)
print(sds.mark1)
print(sds.mark2)
print(sds.mark3)
The output of the above program is:
swift
98
89
76
Subclass
A subclass refers to a new class created based on an existing class.
To specify a superclass for a class, place the superclass name after the subclass name, separated by a colon (:), in the following syntax:
class SomeClass: SomeSuperclass {
// Class definition
}
Example
In the following example, we define a superclass StudDetails
and then create a subclass Tom
that inherits from it:
class StudDetails {
var mark1: Int
var mark2: Int
init(stm1: Int, results stm2: Int) {
mark1 = stm1
mark2 = stm2
}
func show() {
print("Mark1:\(self.mark1), Mark2:\(self.mark2)")
}
}
class Tom: StudDetails {
init() {
super.init(stm1: 93, results: 89)
}
}
let tom = Tom()
tom.show()
The output of the above program is:
Mark1:93, Mark2:89
Overriding
A subclass can implement its own custom functionality by overriding inherited instance methods, class methods, instance properties, or subscript scripts. This behavior is called overriding.
We use the override
keyword to implement overriding.
Accessing Superclass Methods, Properties, and Subscript Scripts
You can access the superclass methods, properties, or subscript scripts by using the super
prefix.
Overriding | Accessing Methods, Properties, Subscript Scripts |
---|---|
Method | super.someMethod() |
Property | super.someProperty() |
Subscript Script | super[someIndex] |
Overriding Methods and Properties
Overriding Methods
We can use the override
keyword to override methods in our subclass.
In the following example, we override the show()
method:
class SuperClass {
func show() {
print("This is the superclass SuperClass")
}
}
class SubClass: SuperClass {
override func show() {
print("This is the subclass SubClass")
}
}
let superClass = SuperClass()
superClass.show()
let subClass = SubClass()
subClass.show()
The output of the above program is:
This is the superclass SuperClass
This is the subclass SubClass
Overriding Properties
You can override properties in a subclass using the override
keyword.
You can provide custom getter (or setter) to override any inherited property, whether the inherited property is a stored property or a computed property.
The subclass does not know whether the inherited property is a stored property or a computed property; it only knows that the inherited property will have a name and a type. Therefore, when you override a property, you must specify both its name and type.
Important points:
- If you provide a setter in the overridden property, you must also provide a getter.
- If you do not want to modify the inherited property value in the overridden getter, you can directly return the inherited value using
super.someProperty
, wheresomeProperty
is the name of the property you are overriding.
The following example defines a superclass Circle
and a subclass Rectangle
. In the Rectangle
class, we override the area
property:
class Circle {
var radius = 12.5
var area: String {
return "Rectangle radius \(radius) "
}
}
// Inherit from superclass Circle
class Rectangle: Circle {
var print = 7
override var area: String {
return super.area + " , but now overridden as \(print)"
}
}
let rect = Rectangle()
rect.radius = 25.0
rect.print = 3
print("Radius \(rect.area)")
The output of the above program is:
Radius Rectangle radius 25.0 , but now overridden as 3
Overriding Property Observers
You can add property observers to an inherited property by overriding it. This way, you can monitor changes to the inherited property's value.
Note: You cannot add property observers to inherited constant stored properties or inherited read-only computed properties.
class Circle {
var radius = 12.5
var area: String {
return "Rectangle radius is \(radius) "
}
}
class Rectangle: Circle {
var print = 7
override var area: String {
return super.area + " , but 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)")
The output is:
Radius: Rectangle radius is 25.0 , but now overridden as 3
Radius: Rectangle radius is 100.0 , but now overridden as 21
Preventing Overrides
You can prevent them from being overridden by using the final
keyword.
If you override a final method, property, or subscript, you will get a compile-time error.
You can mark the entire class as final by adding the final
attribute before the class
keyword (final class), making it non-inheritable, otherwise, you will get a compile-time error.
final class Circle {
final var radius = 12.5
var area: String {
return "Rectangle radius is \(radius) "
}
}
class Rectangle: Circle {
var print = 7
override var area: String {
return super.area + " , but 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)")
Due to the use of the final
keyword in the examples above, which does not allow overriding, the execution will result in an error:
error: var overrides a 'final' var
override var area: String {
^
note: overridden declaration is here
var area: String {
^
error: var overrides a 'final' var
override var radius: Double {
^
note: overridden declaration is here
final var radius = 12.5
^
error: inheritance from a final class 'Circle'
class Rectangle: Circle {
^