本文首發(fā)地址
請?jiān)陂喿x本文章時(shí)次和,順手將文中的示例代碼在playground中敲一遍反肋,這樣能加深理解!Lな石蔗!
閱讀該文章大約需要:15分鐘
讀完之后你能獲得:
1、Extension是什么
2畅形、它能做什么
本文全部內(nèi)容基于Swift版本:3.0.1
Extension的基本語法
extension SomeType {
// new functionality to add to SomeType goes here
}
Tip:擴(kuò)展可以為一個(gè)類型添加新的功能养距,但是不能重寫已有的功能。
struct Student {
var name = ""
var age = 1
func print() {
}
}
extension Student {
//改行會報(bào)錯(cuò)`invalid redeclaration print()`重復(fù)聲明print()日熬,重寫變量也是不行的棍厌。
func print() {
}
}
Swift中的Extension可以做什么
我們想知道Extension在Swift中能做些什么,最直接的方法就是查看Swift的官方文檔了竖席。下面是文檔中指出Extension能做的六個(gè)方面耘纱。
- 添加計(jì)算型實(shí)例屬性和計(jì)算型類型屬性
- 定義實(shí)例方法和類型方法
- 提供新的構(gòu)造器
- 定義下標(biāo)
- 定義和使用新的嵌套類型
- 使已存在的類型遵守某個(gè)協(xié)議
看完上面Extension能做的六個(gè)方面,我們來逐條解釋說明一下:
添加計(jì)算型實(shí)例屬性和計(jì)算型類型屬性
首先我們要了解什么是計(jì)算型屬性毕荐,計(jì)算型屬性(computed property)不直接存儲值束析,而是提供一個(gè)getter
和一個(gè)可選的setter
,來間接獲取和設(shè)置其他屬性或變量的值憎亚。關(guān)于更多的計(jì)算型屬性的內(nèi)容請自行查看官方文檔员寇,在此不再贅述。那么我們什么場景可以用到這個(gè)功能呢虽填?舉一個(gè)最常見的例子丁恭,當(dāng)你想訪問某個(gè)view的width的時(shí)候,通常情況下你會這么寫:
view.frame.size.width
但是這樣寫很長很不方便斋日,作為一個(gè)懶惰的程序員牲览,這時(shí)候你就要想我能不能縮短訪問該屬性的代碼。不要猶豫了騷年,這時(shí)候你只需要寫一個(gè)UIView的Extension就可以達(dá)到你的目的第献。
extension UIView {
var x: CGFloat { return self.frame.origin.x }
var y: CGFloat { return self.frame.origin.y }
var width: CGFloat { return self.frame.size.width }
var height: CGFloat { return self.frame.size.height }
}
這樣你就可以通過來訪問該屬性贡必。怎么樣庸毫,有沒有感受到Extension的便利之處仔拟。
view.width
定義實(shí)例方法和類型方法
在你辛辛苦苦寫完一個(gè)Student類后,萬惡的產(chǎn)品過來告訴你需求改了飒赃,這時(shí)雖然你心中有一萬只草泥馬在奔騰利花,但是為了心中那份神圣的程序員的責(zé)任感(當(dāng)然還有糊口的工資),你還是要修改代碼载佳。如果你想在不改變原始類的基礎(chǔ)上添加功能炒事,那你可以給Student類添加Extension來解決問題。
Tip:這里值得注意的一點(diǎn)是在Swift中蔫慧,Extension可以給類和類型添加挠乳,比如你也可以給一個(gè)struct添加Extension,而在Objective-C中姑躲,你只能給類添加Extension睡扬。
class Student {
var name = ""
var age = 1
}
extension Student {
func printCurrentStudentName() {
print(self.name)
}
}
var jack = Student()
jack.name = "jack"
jack.printCurrentStudentName()
提供新的構(gòu)造器(Initializers)
最常見的Rect通常由origin
和size
來構(gòu)造初始化,但是如果在你寫完Rect的定義后黍析,你偏偏想要通過center和size來確定Rect(作為一個(gè)程序員就要有一種作死的精神)卖怜,那你就要用Extension來給Rect提供一個(gè)新的構(gòu)造器。關(guān)于更多關(guān)于構(gòu)造器的信息橄仍,請參考官方文檔
本例子來源官方文檔
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()
}
let defaultRect = Rect()
let memberwiseRect = Rect(origin: Point(x: 2.0, y: 2.0),
size: Size(width: 5.0, height: 5.0))
通過Extension來給Rect添加一個(gè)新的構(gòu)造器韧涨。
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)
}
}
這樣你就可以通過新的構(gòu)造器來初始化Rect。
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)
定義下標(biāo)
通過Swift中的Extension侮繁,你可以給已知類型添加下標(biāo)虑粥。例如下面的例子就是給Int
類型添加一個(gè)下標(biāo),該下標(biāo)表示十進(jìn)制數(shù)從右向左的第n個(gè)數(shù)字宪哩。
本例子來源官方文檔
extension Int {
subscript(digitIndex: Int) -> Int {
var decimalBase = 1
for _ in 0..<digitIndex {
decimalBase *= 10
}
return (self / decimalBase) % 10
}
}
746381295[0]
// 5
746381295[1]
// 9
定義和使用新的嵌套類型(nest type)
Extensions可以給已知的類娩贷、結(jié)構(gòu)體、枚舉添加嵌套類型锁孟。下面的例子是給Int類型添加一個(gè)判斷正負(fù)數(shù)的Extension彬祖,該Extension嵌套一個(gè)枚舉。
本例子來源官方文檔
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
default:
return .negative
}
}
}
func printIntegerKinds(_ numbers: [Int]) {
for number in numbers {
switch number.kind {
case .negative:
print("- ", terminator: "")
case .zero:
print("0 ", terminator: "")
case .positive:
print("+ ", terminator: "")
}
}
print("")
}
printIntegerKinds([3, 19, -27, 0, -6, 0, 7])
// Prints "+ + - 0 - 0 + "
使已存在的類型遵守某個(gè)協(xié)議
編寫使該類型遵守某個(gè)協(xié)議的Extension的語法如下:
extension SomeType: SomeProtocol, AnotherProtocol {
// implementation of protocol requirements goes here
}
示例代碼:
protocol StudentProtocol {
var address: String { get }
}
struct Student {
var name = ""
var age = 1
}
extension Student: StudentProtocol {
var address: String {
return "address"
}
}
var jack = Student()
jack.address
//輸出 address
若添加Extension的類型已經(jīng)實(shí)現(xiàn)協(xié)議中的內(nèi)容品抽,你可以寫一個(gè)空的Extension來遵守協(xié)議:
protocol StudentProtocol {
var address: String { get }
}
struct Student {
var address: String {
return "address"
}
var name = ""
var age = 1
}
extension Student: StudentProtocol {}
var jack = Student()
jack.address
//輸出 address
總結(jié)
- Extension可以為一個(gè)已有的類储笑、結(jié)構(gòu)體、枚舉類型或者協(xié)議類型添加新功能圆恤。
- 可以在沒有權(quán)限獲取原始源代碼的情況下擴(kuò)展類型的內(nèi)容
- Extendion和Objective-C中的Category類似突倍。(OC中的Category有名字,Swift中的擴(kuò)展沒有名字)
下篇預(yù)告:Swift-Protocol
若本文有何錯(cuò)誤或者不當(dāng)之處,還望不吝賜教羽历。謝謝焊虏!