The Swift Programming Language学习笔记(二十二)——扩展
扩展
Swift 中的扩展可以:
在Swift中,你甚至可以对协议进行扩展,提供协议要求的实现,或者添加额外的功能,从而可以让符合协议的类型拥有这些功能。 注意,扩展可以为一个类型添加新的功能,但是不能重写已有的功能。 扩展语法使用关键字extension来声明扩展。可以通过扩展来扩展一个已有类型,使其采纳一个或多个协议。在这种情况下,无论是类还是结构体,协议名字的书写方式完全一样。 如果你通过扩展为一个已有类型添加新功能,那么新功能对该类型的所有已有实例都是可用的,即使它们是在这个扩展定义之前创建的。 计算型属性扩展可以为已有类型添加计算型实例属性和计算型类型属性。 扩展可以添加新的计算型属性,但是不可以添加存储型属性,也不可以为已有属性添加属性观察器。 extension Double {
var km: Double { return self * 1000 } // 计算型属性必须是var,即使是常量
var m : Double { return self }
var cm: Double { return self / 100.0 }
var mm: Double { return self / 1000.0 }
var ft: Double { return self / 3.28084 } // 一米有3.28024英尺
}
let a = 1.0.cm
print(a) // 0.01
let b = 1.km // 1看成是Double型
print(b) // 1000.0
let aMarathon = 42.km + 195.m
print(aMarathon) // 42195.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()
}
let r1 = Rect()
print(r1) // Rect(origin: Point(x: 0.0,y: 0.0),size: Size(width: 0.0,height: 0.0))
let r2 = Rect(origin: Point(x: 10,y: 10),size: Size(width: 800,height: 640))
print(r2) // Rect(origin: Point(x: 10.0,y: 10.0),size: Size(width: 800.0,height: 640.0))
extension Rect {
init(center: Point,size: Size) {
let x = center.x - size.width / 2
let y = center.y - size.height / 2
self.init(origin: Point(x: x,y: y),size: size)
}
}
let r3 = Rect(center: Point(x: 20,y: 20),size: Size(width: 5,height: 4))
print(r3) // Rect(origin: Point(x: 17.5,y: 18.0),size: Size(width: 5.0,height: 4.0))
方法扩展可以为已有类型添加新的实例方法和类型方法。 extension Int {
func repetitons(task: () -> Void) { for _ in 0..<self { task() } } } 3.repetitons({ print("Hello") }) // 可以使用尾随闭包让调用更加简洁 5.repetitons { print("OK") }
可变实例方法通过扩展添加的实例方法也可以修改该实例本身。结构体和枚举类型中修改 extension Int {
mutating func square() -> Int {
return self * self
}
}
var a = 3 // 必须使用变量调用!不能使用常量或者字面值量
print(a.square())
下标扩展可以为已有类型添加新下标。 extension Int {
subscript(var index: Int) -> Int {
var base = 1
while index > 0 {
base *= 10
--index
}
return (self / base) % 10
}
}
print(1234567890[0]) // 0
print(1234567890[2]) // 8
print(1234567890[11]) // 0,如果该Int值没有足够的位数,即下标越界,那么上述下标实现会返回0,犹如在数字左边自动补0
嵌套类型扩展可以为已有的类、结构体和枚举添加新的嵌套类型。 extension Int {
enum Kind {
case Negative,Zero,Positive
}
var kind: Kind {
switch self {
case 0:
return .Zero
case let x where x > 0:
return .Positive
//case let x where x < 0: // 貌似完备了,但是依然报错没有default
default:
return .Negative
}
}
}
func printIntegerKind(numbers: [Int]) {
for number in numbers {
switch number.kind {
case .Negative: // 由于已知number.kind是Int.Kind类型,因此在switch语句中,Int.Kind中的所有成员值都可以使用简写形式,例如使用. Negative而不是Int.Kind.Negative
print("-",terminator: "、")
case .Zero:
print("0",terminator: "、")
case .Positive:
print("+",terminator: "、")
}
}
print("")
}
let numbers = [1,-23,0,12,45,3,-234]
printIntegerKind(numbers) // +、-、0、+、+、-、+、-、
(编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |