Swift Extensions
Extensions add new functionality to an existing class, structure, or enumeration type.
Extensions can add new functionality to a type, but they cannot override existing functionality.
Extensions in Swift can:
- Add computed properties and computed static properties
- Define instance methods and type methods
- Provide new initializers
- Define subscripts
- Define and use new nested types
- Make an existing type conform to a protocol
Syntax
Extensions are declared using the extension keyword:
extension SomeType {
// New functionality to add to SomeType goes here
}
An extension can extend an existing type to make it adopt one or more protocols, with the following syntax:
extension SomeType: SomeProtocol, AnotherProtocol {
// Protocol implementations go here
}
Computed Properties
Extensions can add computed instance properties and computed type properties to existing types.
Example
The following example adds five computed instance properties to the Int type and extends its functionality:
extension Int {
var add: Int { return self + 100 }
var sub: Int { return self - 10 }
var mul: Int { return self * 10 }
var div: Int { return self / 5 }
}
let addition = 3.add
print("Value after addition: \(addition)")
let subtraction = 120.sub
print("Value after subtraction: \(subtraction)")
let multiplication = 39.mul
print("Value after multiplication: \(multiplication)")
let division = 55.div
print("Value after division: \(division)")
let mix = 30.add + 34.sub
print("Result of mixed operations: \(mix)")
Output of the above program is:
Value after addition: 103
Value after subtraction: 110
Value after multiplication: 390
Value after division: 11
Result of mixed operations: 154
Initializers
Extensions can add new initializers to existing types.
This allows you to extend other types to accept your own custom types as initializer parameters, or to provide additional initialization options not included in the type's original implementation.
Extensions can add new convenience initializers to a class, but they cannot add new designated initializers or deinitializers.
struct Sum {
var num1 = 100, num2 = 200
}
struct Diff {
var no1 = 200, no2 = 100
}
struct Mult {
var a = Sum()
var b = Diff()
}
extension Mult {
init(x: Sum, y: Diff) {
_ = x.num1 + x.num2
_ = y.no1 + y.no2
}
}
let a = Sum(num1: 100, num2: 200)
let b = Diff(no1: 200, no2: 100)
let getMult = Mult(x: a, y: b)
print("getMult sum(\(getMult.a.num1, getMult.a.num2))")
print("getMult diff(\(getMult.b.no1, getMult.b.no2))")
Output of the above program is:
getMult sum(100, 200)
getMult diff(200, 100)
Methods
Extensions can add new instance methods and type methods to existing types.
The following example adds a new instance method called topics
to the Int type:
extension Int {
func topics(summation: () -> ()) {
for _ in 0..<self {
summation()
}
}
}
4.topics({
print("Inside extension block")
})
3.topics({
print("Inside type casting block")
})
Output of the above program is:
Inside extension block
Inside extension block
Inside extension block
Inside extension block
Inside type casting block
Inside type casting block
Inside type casting block
The topics
method takes a single argument of type () -> ()
, indicating that the function has no parameters and returns no value.
After defining this extension, you can call the topics
method on any integer, which will execute a task multiple times.
Mutable Instance Methods
Instance methods added through extensions can also modify the instance itself.
Methods in structures and enumerations that modify self
or its properties must mark the instance method as mutating
, just like mutating methods from the original implementation.
Example
The following example adds a new mutating method called square
to Swift's Double
type, which calculates the square of the original value:
extension Double {
mutating func square() {
let pi = 3.1415
self = pi * self * self
}
}
var Trial1 = 3.3
Trial1.square()
print("The area of the circle is: \(Trial1)")
var Trial2 = 5.8
Trial2.square()
print("The area of the circle is: \(Trial2)")
var Trial3 = 120.3
Trial3.square()
print("The area of the circle is: \(Trial3)")
The output of the above program is:
The area of the circle is: 34.210935
The area of the circle is: 105.68006
The area of the circle is: 45464.070735
Subscripts
Extensions can add new subscripts to an existing type.
Example
The following example adds an integer subscript to Swift's built-in Int
type. This subscript [n]
returns the decimal digit:
extension Int {
subscript(var multtable: Int) -> Int {
var no1 = 1
while multtable > 0 {
no1 *= 10
--multtable
}
return (self / no1) % 10
}
}
print(12[0])
print(7869[1])
print(786543[2])
The output of the above program is:
2
6
5
Nested Types
Extensions can add new nested types to existing classes, structures, and enumerations:
extension Int {
enum calc {
case add
case sub
case mult
case div
case anything
}
var print: calc {
switch self {
case 0:
return .add
case 1:
return .sub
case 2:
return .mult
case 3:
return .div
default:
return .anything
}
}
}
func result(numb: [Int]) {
for i in numb {
switch i.print {
case .add:
print(" 10 ")
case .sub:
print(" 20 ")
case .mult:
print(" 30 ")
case .div:
print(" 40 ")
default:
print(" 50 ")
}
}
}
result([0, 1, 2, 3, 4, 7])
The output of the above program is:
10
20
30
40
50
50