每天學一點Swift----面向對象下(八)

十五.可選協議

1. Swift還支持在協議中定義定義可選成員要求(包括屬性、方法、下標,不包括構造器)----是可選成員要求,不是可選成員。可選成員要求的意思是:該協議的實現類型既可以實現這些協議成員,也可以不實現這些協議成員。


2. 只要在協議成員前添加關鍵optional關鍵字即可定義可選協議。


3. 由於協議的實現者可以不實現可選協議的要求,因此程序面向對象編程時,調用可選協議的可選成員時,推薦使用可選鏈(需要在屬性、方法、下標後添加問號)調用,這樣可以避免當該成員沒有被實現時導致的運行時錯誤,調用可選成員的返回值總是可選值。


4.由於可選協議主要是爲了保持與Objective-C協議的兼容性,因此可選協議必須添加@objc修飾----@objc用於聲明類、協議可以被Objective-C調用。即使該協議不打算被Objective-C調用,也必須添加@objc修飾。不僅如此,可選協議 只能  被類實現,不能被枚舉、結構體實現,所以,可選協議一定是唯類協議。


5. 舉個栗子: 

@objc protocol MyProtocol

{

  //定義可選屬性

  optional var status : String {get}

  //定義可選方法

  optional func test(val : Int)

  //定義可選下標

  optional subscorpt(ids : Int) -> {get}

}


上面定義了一個協議,使用了@objc修飾,因此該協議一定是一個唯類協議,而且該協議可以包含可選成員。

既然MyProtocol協議的所有成員都是可選的,因此可以定義一個空類來實現該協議

//定義一個空類,實現MyProtocol協議,但並不實現該協議的任何成員

class EmptyClass : MyPtorocol

{}


6. 關聯到3中的知識點,在使用可選協議調用可選屬性、可選下標時可以不使用可選鏈----不管程序使用使用可選鏈,調用可選成員總是返回可選值。   使用可選協議調用可選方法時,Swift要求必須  使用可選鏈。


十六.輸出實例和Printable協議

1. 假設有一個Person,實例爲:var peron = Person(),print(person)輸出Person實例後,將看到:PrintInstance.Person,這個結果沒有太大的意義。


2. 如果希望輸出實例時,能真正看到該實例的內部狀態,可以讓該實例實例實現Prinable協議,並實現呢協議中的description只讀屬性。


3. description只讀屬性是一個非常特殊的屬性,它是一個自我描述屬性,該屬性的返回值通常用於實現這樣一個功能:當程序直接輸出該實例時,系統將輸出該實例的自我描述信息,用於告訴外界該實例具有的狀態信息。


4. 舉個栗子:

class Person : Printable

{

   var name : String

   var age : Int

   init(name : String, age : Int)

   {

self.name = name

self.age = age

   }

   //Printable中的只讀屬性

   var description : String

   {

return "msg: (\name) and (\age)"

   }

}


則下面兩個代碼的結果完全相同:

print(person)

print(person.description)


十七.使用自定義類型作爲字典的key

1. 前面學習字典的時候,總是使用系統的IntString等作爲key。這裏將要學習使用自定義類型作爲字典的key


2. 在字典中,不允許出現相同的兩個key。只要兩個key滿足一下兩個條件,字典就會認爲他們相等:

1)兩個key通過==比較返回true

2)兩個keyhashValue屬性返回相等的整數。


3. 但是自定義類型的實例無法通過==進行比較,自定義類型的實例也沒有hashValue屬性,爲了讓自定義類型滿足上述兩個條件,自定義類型必須進行如下改造:

1)讓自定義類型實現Equatable協議,並重載==比較運算符,是的自定義類型的實例可以通過==進行比較。

2)讓自定義類型實現Hashable協議,並實現協議中的hashValue只讀屬性。實現hashValue只讀屬性時,應該和重載的==保持一致。也就是說,當兩個實例通過==比較返回true時,兩個實例的hashValue也應該相等。----實現Equatable協議,並重載==運算符實際上就是重新定義了一個名爲==的函數,方法中的內容由自己提供認爲相等的標準。


4. HashableEquatable協議都是Swift提供的協議,而且Hashable協議是Equatable的子協議,因此自定義類型只要實現Hashable協議即可。


5. 通常而言,正確地重載==運算符應該滿足以下條件:

1)自反性:對任意xx==x應該返回true

2)對稱性:對任意xy,如果x==y返回true,那麼y==x也返回true

3)傳遞性:對任意xyz,如果x==y返回truey==z返回true,則x==z一定返回true

4)一致性:對任意xy,如果實例中用於等價比較的關鍵信息沒有改變,那麼無論x==y調用多少次,返回的結果都應該保持一致,


6.舉個栗子:

class User : Equatable, Printable

{

   var name : String

   var pwd : String

   var age : Int

   init(name : String, pwd : String, age : Int)

   {

self.name = name

self.pwd = pwd

self.age = age

   }

   var hashValue : Int

   {

//根據namepwdhashValue來計算User實例的hashValue

//考慮到數據可能溢出,故此處採用溢出運算符

return name.hashValue &* 31 &+ pwd.hashValue

   }

   var description : String

   {

return "User{\(name),\(pwd),\(age)}"

   }


   //重載==運算符

   func == (lhs : User, rhs : Usr)

   {

return lhs.name == rhs.name && lhs.pwd == rhs.pwd

   }

}


上面的User類滿足了上面3中所說的兩個條件,因此這個類的實例可以作爲字典的key


上一篇:每天學一點Swift----面向對象下(七)

下一篇:每天學一點Swift----面向對象下(九)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章