iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 27
0
Software Development

給我 30 天,給你一輩子:Swift 從零開始系列 第 27

Day 27 | Swift Protocol 與 Extension:Extension 篇

  • 分享至 

  • xImage
  •  

Extension 擴展

在上一篇介紹了使用協定來規範應該實作的屬性、方法或是建構式,今天要來聊到如何使用 Extension 茁壯 Protocol 的方式。

Extension 語法

extension 型別/協定 {
	...
}

Extension 使用

可以使用 Extension 擴展原本型別,在不透過更改既有型別的內容,來新增的東西,來看個範例:

protocol Flying {
    static func fly()
}

struct Person: Flying { }

extension Flying {
    static func fly() {
        print("I can fly!")
    }
}

Person.fly()
// I can fly!

Flying 協定中定義了一個型別方法 fly(),原本 Person struct 應該要實作這個型別方法,但是我們透過 extension 來延伸這個協定,在裡面定義了 fly() 的實作方式,所以我們在 Person struct 就不用在實作 fly() 方法。

protocol People {
    var name: String { get }
}

extension People {
    var name: String {
        "安竹皮皮"
    }
}

struct 人: People { }
let andrew = 人()
print(andrew.name)

屬性也是一樣,都可以用 extension 來擴展。

但並不是使用 extension 擴展就不能在原有的型別中定義同樣的屬性或是方法,還是可以的,而且如果既有型別中有特別定義的話,還是會以自己的為主:

protocol Engineer {
    func attendMeeting()
}

extension Engineer {
    func attendMeeting() {
        print("Go!")
    }
}

struct SeniorEngineer: Engineer {
    func attendMeeting() {
        print("So busy, No way!")
    }
}

let developer = SeniorEngineer()
developer.attendMeeting()
// So busy, No way!

定義了一個協定 Engineer,Engineer 要開會,有一個 attendMeeting() 方法必須實作,這邊使用了 extension 來定義實作詳細方式,print("Go!"),但是在 SeniorEngineer 結構中雖然遵循了 Engineer Protocol,但是資深工程師總是忙碌了一點,對於參加會議另外定義了方法,實作內容為 print("So busy, No way!"),儘管在擴展協定中有定義好 attendMeeting() 的實作內容,但是既有的型別中如果也有定義的話,會先以自己的為主喔。

透過 Extension 遵循 Protocol

protocol Engineer {
    func attendMeeting()
}

struct SeniorEngineer {
    func attendMeeting() {
        print("No way!")
    }
}

extension SeniorEngineer: Engineer { }

SeniorEngineer 結構,雖然有時做 attendMeetin() 方法,但是沒有遵循 Engineer Protocol,即使滿足了協定中的要求,也不會自動遵循 Protocol,除非我們自己加上要遵循的 Protocol。

透過 extension,我們可以擴展這個結構,事後來遵循 Engineer Protocol。

Class-Only Protocol

我們在定義協定時,可以在協定名稱後方加上 : class,這樣這個協定就只有 Class 的相關型別才能夠遵循:

protocol Engineer: class {
    func attendMeeting()
}

struct SeniorEngineer {
    func attendMeeting() {
        print("No way!")
    }
}

extension SeniorEngineer: Engineer { }
// error: Non-class type 'SeniorEngineer' cannot conform to class protocol 'Engineer'

如果不是 Class 型別來遵循時,就會跳出 Non-class type 'SeniorEngineer' cannot conform to class protocol 'Engineer' 這種錯誤訊息。


Extension 除了可以用於 Protocol,還可以被具有封裝特性的型別來使用喔,所以舉凡 Class、Struct 以及 Enum 都可以來使用 extension 來擴展型別或是協定喔。

Extension 讓我們可以在不碰到既有型別的原始碼,可以加上自定義的一些功能,這種方式就稱為 Retrospective Modeling/images/emoticon/emoticon06.gif


上一篇
Day 26 | Swift Protocol 與 Extension:Protocol 篇
下一篇
Day 28 | Swift Error Handling
系列文
給我 30 天,給你一輩子:Swift 從零開始30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言