table of Contents
version
Xcode 11.3.1
Swift 5.1.3
Expand
Extensions can add new functions to an existing class, structure, enumeration, and protocol, but cannot rewrite existing functions.
Extensions in Swift can:
- Add calculated attributes (stored attributes cannot be added)
- Define instance methods and class methods
- Provide a new constructor
- Define subscript
- Define and use new nested types
- Make an existing type conform to a certain protocol
grammar
extension SomeType {
// 在这里给 SomeType 添加新的功能
}
Calculated attributes
Extensions can add calculated instance attributes and calculated class attributes to existing types.
1. Calculated instance attributes
extension Int {
var add: Int {
return self + 10
}
var sub: Int {
return self - 10
}
}
let addition = 15.add
let substraction = 15.sub
print(addition, substraction)
// 25 5
2. Calculated class attributes
struct AA {
static var num = 10
}
extension AA {
static var aad: Int {
return self.num + 10
}
}
let aa = 5.add
print(aa)
// 15
As mentioned before, extensions cannot add stored attributes. For example, in the above example, adding the following extension to the class attribute num of AA will cause a compilation error:
static var num: Int {
return self.num + 10
}
method
Extensions can add new instance methods and class methods to existing types.
1. Example method
class Counter {
var count = 0
}
extension Counter {
func increment() -> Int {
return count + 1
}
}
let counter = Counter()
let currentCount = counter.increment()
print(currentCount)
// 1
2. Class methods
extension Int {
static func printFunc() {
print("我被打印了")
}
}
Int.printFunc()
// 我被打印了
Constructor
Extensions can add new constructors to existing types.
Extensions can add new convenience initializers to the class, but they cannot add new designated initializers or deinit() to the class.
struct Size {
var width = 0.0, height = 0.0
}
struct Point {
var x = 0.0, y = 0.0
}
struct Rect {
var origin = Point()
var size = Size()
}
extension Rect {
init(center: Point, size: Size) {
let originX = center.x - (size.width / 2)
let originY = center.y - (size.height / 2)
self.init(origin: Point(x: originX, y: originY), size: size)
}
}
let centerRect = Rect(center: Point(x: 5.0, y: 5.0), size: Size(width: 4.0, height: 4.0))
print(centerRect.origin)
// Point(x: 3.0, y: 3.0)
Because the Rect structure provides default values for all attributes (origin and size), it automatically obtains a default constructor and a member constructor. These constructors can be used to create new Rect instances.
This new constructor first calculates an appropriate origin based on the provided center and size. Then this constructor calls the member constructor init(origin:size:) that comes with the structure, which stores the new origin and size values in the appropriate attributes.
Subscript
Extensions can add new subscripts to existing types.
In the following example, an integer subscript is added to the Int type of Swift. The subscript [n] starts from the right side of the number and returns to the nth place after the decimal point:
extension Int {
subscript(digitIndex: Int) -> Int {
var decimalBase = 1
for _ in 0..<digitIndex {
decimalBase *= 10
}
return (self / decimalBase) % 10
}
}
print(123[0])
// 3
print(123[1])
// 2
print(123[2])
// 1
Nested type
Extensions can add new nested types to existing classes, structures, and enumerations:
extension Int {
enum calculate
{
case add
case sub
case mult
}
var print: calculate {
switch self
{
case 0:
return .add
case 1:
return .sub
default:
return .mult
}
}
}
func result(numb: [Int]) {
for i in numb {
switch i.print {
case .add:
print("10")
case .sub:
print("20")
case .mult:
print("30")
}
}
}
result(numb: [1, 2, 0])
/**
20
30
10
*/