Swift中 protocol的學習
//擴展標準庫/定義屬于個人的協議的學習
//--------------- SomeProtocol ---------------//
protocol SomeProtocol {
? ? ? ? //1.
? ? ? ? ?func f()
? ? ? ? ? //2. 用關鍵字 'static' 來聲明類方法
? ? ? ? ? ?static func someTypeMethod(_ type: String)
? ? ? ? ? //3. 構造器方法
? ? ? ? ? ?init(someParameter: Int)
}
//定義Wjq類, 并遵守 'SomeProtocol' 協議
//實現協議的類型除了 class 外,還可以是 struct 或 enum。
/*-----實現協議的方式一 -----*/
class Wjq: SomeProtocol{
//1.
? ? ? ? ? ?func f() { ? ? ? ? ?print("定義類, 并直接在當前類遵守 'SomeProtocol' 協議") ? }
//2. 如果實現該協議的類型是class 類型, 則在實現類中除了用static 來修飾類方法外, 還可以用class來修飾
//這里也可以用 static 修飾,區別是 static 修飾的屬性或方法不能被子類復寫,class 修飾的可以被子類復寫
? ? ? ? ? class func someTypeMethod(_ type: String) {
? ? ? ? ? ? ? ? print("type Method")
? ? ? ? }
//3. 遵循協議的類型實現指定的構造器:
//注意: 在符合協議的類中實現構造器,必須在構造器實現前加上 required 修飾符。使用 required 修飾符可以確保所有子類也必須提供此構造器實現,從而也能符合協議。 如果類已經被標記為 final,那么不需要在協議構造器的實現中使用 required 修飾符,因為 final 類不能有子類.
? ? ? ? required init(someParameter: Int) {
? ? ? ? ? ? //初始化
? ? ? ? }
}
/*-----實現協議的方式二 定義類, 通過 'extension(擴展)' 實現協議-----*/
/*class Wjq{
}
extension Wjq: SomeProtocol {
? ? ? ? ? ? func f() {
? ? ? ? ? ? ? ?print("定義類, 通過 'extension(擴展)' 實現協議")
? ? ? ? ? ?}
}
*/
//子類
class wj: Wjq {
? ? ? ? ? ? override func f() {
? ? ? ? ? ? ? print("當子類復寫父類的方法或計算屬性時才需要用 override 修飾")
? ? ? ? ?}
}
//---------------? MyProtocol ---------------//
//協議中聲明屬性和方法
protocol MyProtocol {
? ? ? ? ? ? var prop: Int { get set } // { set get } 來表示屬性是可讀可寫的
? ? ? ? ? ? ?var propertyWithImplementation: String { get } //用 { get } 來表示屬性是只讀的
? ? ? ? ? ? func foo()
? ? ? ? ? ? //注意: 協議里面聲明的屬性和方法一定是抽象的,不能有實現,由符合協議的類型來提供所有屬性和方法的實現。
}
//MARK: -- 通過擴展協議達到為協議中的'屬性'和'方法'提供默認實現的目的
extension MyProtocol{
? ? ? var propertyWithImplementation: String {return "通過擴展協議使得'屬性' 有默認實現"}
? ? ? func foo()? { ? print(prop) ? }
? ? ? //在 'extension' 中添加 'MyProtocol' 協議中沒有定義過的屬性和方法
? ? ? ? ? ?var exceed: Double { return 23 }
? ? ? ?func isExceed() -> Bool { ? return prop > 30 ?}
}
class MyClass: MyProtocol {
var prop: Int = 20
}
//---------------? TextRepresentable? --------------//
protocol TextRepresentable {
var textualDescription: String { get }
}
// 實現協議的關鍵字 --> struct
struct Hamster: TextRepresentable {
var name: String
var textualDescription: String{
return "A hamster named \(name)"
}
}
//在擴展協議的時候,還可以指定一些限制條件,只有遵循協議的類型滿足這些限制條件時,才能獲得協議擴展提供的默認實現。
//這里擴展了 Swift 標準庫中的 Collection 協議,但是限制只適用于集合中的元素遵循了 TextRepresentable 協議的情況。 因為 Swift 中 Array 符合 Collection 協議,而 Hamster 類型又符合 TextRepresentable 協議,所以 hamsters 可以使用 textualDescription 屬性得到數組內容的文本表示。
extension Collection where Iterator.Element: TextRepresentable{
var textualDescription: String {
let itemsAsText = self.map { $0.textualDescription }
return "[" + itemsAsText.joined(separator: ", ") + "]"
}
}
//------------------協議中可以定義可變方法-----------------//
protocol Togglable {
? ? ? ? ?mutating func toggle()
}
enum OnOffSwitch: Togglable {
? ? ? ? case off, on
? ? ? ?mutating func toggle() {
? ? ? ? ? ?switch self {
? ? ? ? ? case .off:
? ? ? ? ?self = .on
? ? ? ? ?case .on:
? ? ? ? self = .off
? ? ? ?}
? ? }
}
//上面展示了實現協議的三種類型 class , struct , enum。
//如果想要限制協議只能被 Class 類型遵循,而結構體或枚舉不能遵循該協議。 我們還可以讓協議繼承 AnyObject 來實現
protocol onlyClassImplementation: AnyObject {
func onlyClass()
}
class onlyClass: onlyClassImplementation {
func onlyClass() {
//
}
}
//報錯
//struct cla:? onlyClassImplementation {
//
//}
//------------? 協議組合? ---------------------//
protocol Name {
var name: String { get }
}
protocol Age {
var age: Int { get }
}
struct Pers: Name, Age {
var name: String
var age: Int
}
//------------? 協議還可以與類進行組合? ---------------------//
class Location {
var latitude: Double
var longitude: Double
init(latitude: Double, longitude: Double) {
self.latitude = latitude
self.longitude = longitude
}
}
class City: Location, Name {
var name: String
init(name: String, latitude: Double, longitude: Double) {
self.name = name
super.init(latitude: latitude, longitude: longitude)
}
}
/*
協議還可以與類進行組合
func beginConcert(in location: Location & Name) {
print("Hello, \(location.name)!")
}
let seattle = City(name: "Seattle", latitude: 47.6, longitude: -122.3)
beginConcert(in: seattle)
*/
//------------? optional 可選協議? ---------------------//
@objc protocol CounterDataSource {
@objc optional func incrementForCount(count: Int) -> Int
@objc optional var fixedIncrement: Int { get }
//注意:標記為 @objc 的 protocol 只能被 class 實現,不能被 struct 和 enum 類型實現,而且實現它的 class 中的方法也必須被標注為 @objc,或者整個類就是繼承自 NSObject。
}
//------------? delegate ---------------------//
protocol RentHouserDelegate{
func rent(_ name:String)
}
class Tenant {
var name = "ii"
var delegate: RentHouserDelegate?
func rentHouse() {
delegate?.rent(name)
}
}
class Intermediary: RentHouserDelegate {
var name = "aa"
func rent(_ name: String) {
print("\(name) 請 \(self.name) 幫她租一套房子");
}
}
//檢查協議一致性, 可以通過 is ,? as? ,? as 來檢查某個實例是否符合某個協議:
class view: ViewController,Name,Age {
var age: Int = 0
var name: String = ""
override func viewDidLoad() {
var lightSwitch = OnOffSwitch.off
lightSwitch.toggle()
// lightSwitch 現在的值為 .On
//協議組合
func wishHappyBirthday(to celebrator: Name & Age) {
print("Happy birthday, \(celebrator.name), you're \(celebrator.age)!")
}
let birthdayPerson = Pers(name: "Malcolm", age: 21)
wishHappyBirthday(to: birthdayPerson)
// Prints "Happy birthday, Malcolm, you're 21!"
/*? delegate? */
let person = Tenant()
person.delegate = Intermediary()
person.rentHouse()
}
}
Demo:?