swift扩展_Swift Extensions

分享到:

扩展将新增功能添加到现有类、结构体或枚举类型。包括对类型(无法获取其初始源代码时)进行扩展的能力(被称为逆向建模)。扩展类似于Objective-C中的分类(不同之处在于,Swift没有扩展名称)。

Swift中的扩展可以:

添加计算属性和计算静态属性

定义实例方法和类型方法

提供新的初始化函数

定义下标

定义和使用新的嵌套类型

使现有的类型符合协议

注:如果将扩展定义为向现有类型中添加新功能,则这些新功能将在该类型的所有现有实例上可用;即使这些实例是在定义扩展前创建的,也是如此。

 

扩展语法

 

使用关键字声明扩展:

 

extension SomeType {

// new functionality to add to SomeType goes here

}

 

扩展功能可以扩展现有的类型,使其采用一个或多个协议。如果是这种情况,则协议名称以适用于类或结构同样的方法被准确写入:

 

extension SomeType: SomeProtocol, AnotherProtocol {

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

// implementation of protocol requirements goes here

}

 

以此种方式添加协议的一致性-见扩展添加协议一致性下的介绍。

 

计算属性

 

扩展可向现有类型中添加计算型实例属性和计算型类型属性。本示例向Swift的内置Double类型添加了五个计算型实例属性,以便为距离单位的使用提供基本支持:

 

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 oneInch = 25.4.mm

println("One inch is \(oneInch) meters")

prints "One inch is 0.0254 meters"

threeFeet = 3.ft

("Three feet is \(threeFeet) meters")

prints " Three feet is 0.914399970739201 meters"

 

这些计算型属性表示:Double值应被视为某长度单位。即使被作为计算属性实现,这些属性的名称仍可被添加到采用点语法的浮点文字值上,作为一种使用该文字值来执行距离转换的方法。

在这个例子中,人们认为1.0 的Double值是代表“一米”。因此m计算属性返回self-表达式1.m被视为用来计算Double值1.0。

其他单位需要一些转换,被表示为以米为单位测得的值。1

一千米等于1,000米,因此,km计算型属性用1-000.00乘以该值,以转换为以米为单位表示的数字。类似地,一米为3.28024英尺,因此,ft计算属性用3.28024除以基础Double值,以将该值由英尺转换为米制。

这些属性为只读的计算属性,因此,为使其表达简洁,不使用get关键字。它们的返回值为Double类型,并且,在接受Double的情况下,可在数学计算中使用。

 

let aMarathon = 42.km + 195.m

println("A marathon is \(aMarathon) meters long")

// prints "A marathon is 42195.0 meters long"

 

注:扩展可添加新的计算属性,但无法添加存储属性,也无法将属性观察器添加到现有属性。

 

初始化函数

 

扩展功能可以为现有类型添加新的初始化函数。这使得用户可对其他类型进行扩展,以接受自定义属性并将其作为初始化函数参数,或提供未包括在该类型初始缺省参数的其他初始化选项。

扩展可向类中添加新的便利初始化函数,但无法向其中添加新的指定初始化函数或反初始化函数。指定初始化函数和反初始化函数必须始终由原始类实现提供。

注:如果使用扩展向数值类型添加初始化函数,该值类型向存储的属性提供默认值,且不对任何自定义初始化函数进行定义,则可从扩展的初始化函数中调用适用于该值类型的默认初始化函数和按成员初始化函数。 如果已编写初始化函数并将其作为该值类型初始实现的一部分,则情况将有所不同-见适用于值类型的初始化函数委托下的介绍。

 

下面例子定义一个自定义Rect结构体来表示几何矩形。这个例子还定义了2个支撑结构体Size和Point,它们2个都为其属性提供0.0的默认值:

 

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()

 

由于Rect结构体为它的所有属性提供默认值,因此,它会自动收到默认初始化函数和按成员初始化函数-见默认初始化函数下的介绍。这些初始化程序可以用来创建新的实例:

 

let defaultRect = Rect()

let memberwiseRect = Rect(origin: Point(x: 2.0, y: 2.0),

size: Size(width: 5.0, height: 5.0))

 

用户可以扩展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)

}

}

 

该初始化函数以提供的一个center点和一个size数值为依据, 通过计算相应的原点而被启动。然后,该初始化函数调用该结构体的自动按成员初始化函数init(origin:size:),该函数将新原点和尺寸值存储在相应属性中:

 

let centerRect = Rect(center: Point(x: 4.0, y: 4.0),

size: Size(width: 3.0, height: 3.0))

// centerRect's origin is (2.5, 2.5) and its size is (3.0, 3.0)

 

 

注:如果利用扩展提供一个新的初始化函数,则在完成初始化函数后,还应确保各实例均完全初始化。

 

方法

 

扩展可向现有类型中添加新的实例方法和类型方法。下面的示例为Int类型添加了的新的实例方法repetitons:

 

extension Int {

func repetitions(task: () -> ()) {

for i in 0..self {

task()

}

}

}

 

Repetition方法具有一个类型为 () -> ()的单变元,该变元表示一个不含有参数且不返回值的函数。

定义此扩展后,可以调用任何整数上的repetitions方法以执行任务(可执行许多次):

 

3.repetitions({

println("Hello!")

})

// Hello!

// Hello!

// Hello!

 

使用尾随闭包语法,使调用更加简洁:

 

3.repetitions {

println("Goodbye!")

}

// Goodbye!

// Goodbye!

// Goodbye!

 

变异实例方法

 

向实例方法添加扩展后,该方法还可以对其实例本身进行修改(或变异)。修改self或其属性的结构和枚举方法必须将实例方法标记为变异方法,类似于初始实现中的变异方法。

以下示例向Swift的Int类型中添加了一个新的变异方法square,该方法对初始值进行平方运算:

 

extension Int {

mutating func square() {

self = self * self

}

}

var someInt = 3

someInt.square()

// someInt is now 9

 

 

下标

 

扩展功能可以为现有类型添加新的下标。本示例为Swift的内置Int类型添加了一个整数下标。下标[n]返回十进制数字符n并从该数字右侧将n置于其中:   等等:

 

extension Int {

subscript(digitIndex: Int) -> Int {

var decimalBase = 1

for _ in 1...digitIndex {

decimalBase *= 10

}

return (self / decimalBase) % 10

}

}

746381295[0]

returns 5

746381295[1]

returns 9

746381295[2]

returns 2

746381295[8]

returns 7

 

对于所请求的索引,如果Int值没有足够的位数,则下标实现将返回0——这相当于在该数字的左边以零填补:

 

746381295[9]

// returns 0, as if you had requested:

0746381295[9]

 

嵌套类型

 

扩展可向现有类、结构体和枚举中添加新的嵌套类型:

 

extension Character {

enum Kind {

case Vowel, Consonant, Other

}

var kind: Kind {

switch String(self).lowercaseString {

case "a", "e", "i", "o", "u":

return .Vowel

case "b", "c", "d", "f", "g", "h", "j", "k", "l", "m",

n", "p", "q", "r", "s", "t", "v", "w", "x", "y", "z":

return .Consonant

default:

return . Other

}

本示例为字符添加了一个新的嵌套枚举。这个名为Kind的枚举表示某特殊字符所代表的字母的种类。具体来说,它表示该字符在标准拉丁字母中是元音还是辅音(不考虑发音或地域差异),或者该字符是否是另外一种字符。

此示例还向Character中添加了新的名为kind的计算型实例属性,该属性为该字符返回适当的Kind枚举成员。

现在嵌套枚举可以与值一起使用:

 

func printLetterKinds(word: String) {

println("'\(word)' is made up of the following kinds of letters:")

for character in word {

switch character.kind {

case .Vowel:

print("vowel ")

case .Consonant:

print("consonant ")

case .Other:

print("other ")

}

print("\n")

printLetterKinds("Hello")

Hello' is made up of the following kinds of letters:

consonant vowel consonant consonant vowel

PrintLetterKinds函数具有一个输入String值并对其字符进行迭代。针对每个字符,该函数均考虑适用于各字符的kind计算属性,并打印出该kind的相应描述。然后,printLetterKinds函数可以被调用,以便以整个单词的形式打印出各种字母,如这里所示的“Helo”。

注:character.kind是已知CharacterKind的类型之一。因此,在语句中,所有Character.Kind的成员值可以以简写形式编写,例如用Vowel代替Character。Kind.Vowel.

昵    称:
验证码:

相关文档:

swift
IOS实例
ObjectiveC