Swift学习笔记

Swift - 11.1 - 协议

2022-03-18  本文已影响0人  aven_kang

协议 - Protoclo

协议可以用来定义方法、属性、下标的声明,协议可以被枚举、结构体、类遵守(多个协议之间用逗号隔开)
protocol Drawable {
    func draw()
    var x:Int {get set}
    var y:Int {get}
    subscript(index i:Int) -> Int {get set}
}

protocol Drawable2 {
    func draw()
    var x:Int {get set}
    var y:Int {get}
    subscript(index i:Int) -> Int {get set}
}

class ViewController: UIViewController,Drawable {
    func draw() {
        
    }
    
    var x: Int = 0
    
    var y: Int = 0
    
    subscript(index i: Int) -> Int {
        get {
            return i
        }
        set {
            
        }
    }
}

协议中定义方法时,不能有默认参数值
默认情况下,协议中定义的内容必须全部实现

为了保证通用性,协议中必须使用static定义类型方法、类型属性、类型下标
protocol Drawable {
    static func draw()
}

因为class只能用在类里面,而协议是可以被结构体和枚举遵守的
所以为了保证通用性,需要加上static,这样大家都能用

mutating

1.只有将协议中的实例方法标记为mutating,才允许结构体、枚举的具体实现修改自身内存
2.类在实现方法时,不用加mutating,枚举、结构体菜需要加mutating
protocol Drawable {
    var x:Int {get set}
    mutating func draw()
}

struct test : Drawable {
  var x:Int = 0
  mutating func draw()  { //加了mutating才允许这样修改x,否则会报错
         x = 10 
     }
}

class test2 : Drawable {
      var x:Int = 0
      func draw(){ //类可以直接修改
          x = 10 
    }
}

init

1.协议中还可以定义初始化器init,非final类实现时必须加上required
protocol testP {
    init(x:Int, y:Int)
}

class Point : testP {
    
    required init(x: Int, y: Int) {
        
    }
}

final class Point2 :testP {
    
    init(x: Int, y: Int) {
        
    }
}
为什么被final修饰的类,不需要加上required,因为final类型的就说明了,这个类是不能被继承的,就可以防止子类在继承的时候,丢了这个初始化操作,保证了安全
截屏2022-02-23 下午1.20.36.png

协议中的init、init?、init!

截屏2022-02-23 下午1.32.51.png

协议的继承

protocol Runnable {
    func run()
}

protocol Liveable : Runnable {
    func breath()
}

class manger : Liveable {
    
    func run() {
        
    }
    
    func breath() {
    
    }
}

协议组合

protocol Runnable {
    func run()
}

protocol Liveable : Runnable {
    func breath()
}

class manger : Liveable {
    
    func run() {
        
    }
    
    func breath() {
    
    }
}

// 接收Person或者其子类的实例
func fn0(obj:manger) {}
// 接受遵守Liveable协议的实例
func fn1(obj:Liveable) {}
// 接收同时遵守Liveable、Runnable协议的实例
func fn2(obj: Liveable & Runnable) {}
//接收同时遵守Liveable、Runnable协议、并且是Person或者其子类的实例
func fn2(obj: manger & Liveable & Runnable) {}

typealias RealPerson = manger & Liveable & Runnable
//接收同时遵守Liveable、Runnable协议、并且是Person或者其子类的实例
func fn4(obj: RealPerson) {}

CaseIterable

让枚举遵守CaseIterable协议,可以实现遍历
截屏2022-02-23 下午1.54.12.png

CustomStringConvertible

遵守这个协议,相当于OC的description会重置这个类的打印方法
class Person : CustomStringConvertible {
    
    var age:Int = 0
    var name:String = "jack"
    
    var description: String {
        
        return "age=\(age),name\(name)"
        
    }
    
}
class ViewController: UIViewController {
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
        var p1 = Person()
        print(p1)
        
    }
}

打印台会打印
age=0,namejack
上一篇下一篇

猜你喜欢

热点阅读