本文参考了Swift2.2与3.0的语法,在少数地方添加了自我理解与示例.
扩展(Extensions)
扩展就是向一个已有的类、结构体、枚举类型或者协议类型 添加新功能。
这包括在没有权限获取原始源代码的情况下扩展类型的能力(即逆向建模)。
扩展和Objective-C中的分类(categories)类似。
(不过与 Objective-C 不同的是,Swift 的扩展没有名字。)
Swift中的扩展可以:
添加计算型属性和计算型静态属性
添加实例方法和类型方法
添加新的构造器
添加下标
添加和使用新的嵌套类型
使一个已有类型符合某个协议
在 Swift 中,你甚至可以对一个协议(Protocol)进行扩展,
(你可以从协议扩展获取更多的细节。)
注意
扩展可以对 一个类型 添加新的功能,但是不能重写已有的功能。
扩展语法(Extension Syntax)
声明一个扩展使用关键字extension
<pre>
<code>
extension SomeType { // 加到SomeType的新功能写到这里 }
</code>
</pre>
一个扩展可以扩展一个已有类型使其能够适配一个或多个协议(protocol)。
<pre>
<code>
//SomeType类型遵循协议SomeProtocol, AnotherProctocol //SomeType类型是协议SomeProtocol, AnotherProctocol的成员 extension SomeType: SomeProtocol, AnotherProctocol { // 协议实现写到这里 }
</code>
</pre>
按照这种方式添加协议遵循者(protocol conformance)被称为在扩展中添加协议成员
注意:
如果你定义了一个扩展向一个已有类型添加新功能
那么这个新功能对该类型的所有已有实例中都是可用的
即使它们是在你的这个扩展的前面定义的。
计算型属性(Computed Properties)
扩展可以向已有类型添加计算型实例属性和计算型类型属性。
下面的例子向 Swift的内建Double类型 添加了5个计算型实例属性
<pre>
<code>
`
extension Double
{
var km: Double { return self * 1_000.0 }
var m : Double { return self }
var cm: Double { return self / 100.0 }
var mm: Double { return self / 1_000.0 }
var ft: Double { return self / 3.28084 }
}
let aNumber = 3.1415
print(aNumber.km)
print(aNumber.m)
print(aNumber.cm)
print(aNumber.mm)
print(aNumber.ft)
//打印
//3141.5
//3.1415
//0.031415
//0.0031415
//0.957529169359067
`
</code>
</pre>
注意
扩展
可以添加新的计算属性
不可以添加存储属性
不可以向已有属性添加属性观测器(property observers)
构造器(Initializers)
扩展可以向已有类型 添加 新的构造器。
扩展
能 向类中添加新的 便利构造器
不能 向类中添加新的 指定构造器 或 析构器。
指定构造器 和 析构器 总是由 原始的类实现 来提供。
注意
如果你使用扩展向 一个值类型 添加 一个构造器,该值类型 已经为所有的存储属性 提供了默认值,而且没有定义任何定制构造器(custom initializers)
你可以在值类型的 扩展构造器中 调用默认构造器(default initializers) 和 逐一成员构造器(memberwise initializers)
下面的例子定义了一个 用于描述几何矩形 的 结构体Rect
<pre>
<code>
`
//定义了两个 结构体Size和Point ,它们都把0.0作为所有属性的默认值:
struct Size
{
var width = 0.0, height = 0.0
}
struct Point
{
var x = 0.0, y = 0.0
}
//结构体Rect
struct Rect
{
var origin = Point()
var size = Size()
}
//在extension中提供一个使用center和size的构造器来扩展Rect结构体:
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)
}
}
//因为结构体Rect提供了其所有属性的默认值,可以使用默认构造器和逐一成员构造器。这些构造器可以用于构造新的Rect实例:
let defaultRect = Rect()//使用默认构造器
let memberwiseRect = Rect(origin: Point(x: 2.0, y: 2.0),size: Size(width: 5.0, height: 5.0))//使用逐一成员构造器
//调用结构体Rect中新提供的构造器构造Rect实例
let centerRect = Rect(center: Point(x: 4.0, y: 4.0),size: Size(width: 3.0, height: 3.0))
`
</code>
</pre>
注意
如果你使用扩展提供了一个新的构造器,你依旧有责任保证构造过程能够让实例完全初始化。
方法(Methods)
扩展可以向已有类型 添加新的 实例方法 和 类型方法。
下面的例子为 Int类型 扩展添加 一个名为repetitions的新实例方法
<pre>
<code>
`
extension Int
{
//repetitions方法使用了一个参数,类型为 () -> () ,即没有参数没有返回值。
//任意整数可以调用repetitions方法,实现多次执行block
func repetitions(task: () -> ())
{ for _ in 0 ..< self { task() }
}
}
5.repetitions { print("hello world") }
//打印
//hello world
//hello world
//hello world
//hello world
//hello world
`
</code>
</pre>
下标(Subscripts)
扩展可以 向一个已有类型 添加 新下标。
eg:
<pre>
<code>
`
extension String
{
enum BigOrSmall
{
case Big
case Small
}
subscript(bigOrSmall: BigOrSmall) -> String
{
switch bigOrSmall
{
case .Big:
return self.uppercaseString
case .Small:
return self.lowercaseString
}
}
}
let someStr = "abc低EFG"
print(someStr[.Big])
print(someStr[.Small])
//打印
//ABC低EFG
//abc低efg
`
</code>
</pre>
嵌套类型(Nested Types)
扩展可以向已有的类、结构体和枚举添加新的嵌套类型
eg.
<pre>
<code>
`
extension Int
{
enum Kind:String
{ case Negative, Zero, Positive }
var kind: Kind
{
switch self
{
case 0: return .Zero
case let x where x > 0: return .Positive
default: return .Negative
}
}
}
for number in [3, 19, -27, 0, -6, 0, 7]{ print(number.kind) }
//打印
//Positive
//Positive
//Negative
//Zero
//Negative
//Zero
//Positive
`
</code>
</pre>