一、引言
協議約定了一些屬性與方法,其作用類似Java中的抽象類,Swift中類型透過遵守協議來實現一些約定的屬性和方法。 Swift中的協定使用protocol關鍵字來聲明。 Swift中的協定還有一個十分有趣的特性,協定可以透過擴展來實現一些方法和附加功能。
二、在協定中定義屬性與方法
協定中定義的屬性只約定名稱和類型,在具體類型的實作中,其可以是儲存屬性也可以是計算屬性,協定中還需要指定屬性是可讀的還是可讀可寫的。範例程式碼如下:
protocol MyPortocol { //定义实例属性 //可读的 var name:String{get} //可读可写的 var age:Int{set get} //可读的 var nameAndAge:String{get} static var className:String{get} } class MyClass: MyPortocol { var name: String var age: Int var nameAndAge: String{ get{ return "\(name)"+"\(age)" } } static var className: String{ get{ return "MyClass" } } init(){ name = "HS" age = 24 } }
有一點要注意,協定中的可讀並不是唯讀,協定中的屬性約定成可讀可寫,則在實作時,這個屬性必須是可讀可寫的,但是如果協定中約定成可讀的,則此屬性可以是唯讀的也可以是可讀可寫的,看具體的實作。
協定中約定的方法可以是實例方法也可以是型別方法,範例如下:
protocol MyPortocol { func logName() static func logClassName() } class MyClass: MyPortocol { var name: String var age: Int init(){ name = "HS" age = 24 } func logName() { print(name) } static func logClassName() { print(className) } }
同樣,協定中也可以對構造方法進行定義約定。
三、協定的特點
協定中雖然沒有任何屬性和方法的實現,但是其仍然可以當做類型來使用,在函數參數、返回值中應用廣泛,示例如下:
protocol MyPortocol { //定义实例属性 var name:String{get} var age:Int{set get} var nameAndAge:String{get} static var className:String{get} func logName() static func logClassName() } //将协议类型作为参数 func test(param:MyPortocol) { param.logName() }
協議作為類型這種用法另一個應用點是在集合類型中,協議可以作為所有遵守此協議的集合類型。
協定可以像其他類型一樣進行繼承,子協定將自動擁有父協定約定的屬性和方法。協定也可以透過class關鍵字來定義只有類別可以遵守,範例如下:
protocol MyPortocol { //定义实例属性 var name:String{get} var age:Int{set get} var nameAndAge:String{get} static var className:String{get} func logName() static func logClassName() } //只有类可以继承此协议 protocol MySubPortocol:class,MyPortocol { }
協議既然可以像其他類型一樣進行使用,當然它也可以使用is,as?,as!進行檢查和轉換,關於is,as的更多用法可以查看Swift關於類型轉換的內容。
協議也可定義其中的屬性或方法為可選的,即遵守此協議的類別可以實現也可以不實現可選的屬性和方法,然而,聲明為可選的需要此協議為@objc類型的,範例如下:
@objc protocol MyPortocol { //定义实例属性 var name:String{get} var age:Int{set get} var nameAndAge:String{get} static var className:String{get} func logName() //可选实现 optional static func logClassName() }
Swift中的協定還有一個十分重要的特性,可以透過擴展來進行屬性、方法以及下標的實作。這對於一些通用類別的方法十分方便,這相當於所有繼承此協定的類別都預設實作了這樣的方法,範例如下:
protocol MyPortocol { //定义实例属性 var name:String{get} var age:Int{set get} var nameAndAge:String{get} static var className:String{get} func logName() static func logClassName() } extension MyPortocol{ var name:String{ return "HS" } }