Swift 协议(Protocol)⑩

  协议可以用来定义方法、属性、下标的生命,协议可以被枚举、结构体、类遵守(多个协议之间用逗号,隔开)


  • 协议中的方法不能有默认值
  • 默认情况下,协议中的内容必须全部实现
  • 协议中定义属性时必须用var关键字
  • 实现协议时的属性权限不能小于协议中定义的属性权限
    1. 协议中定义get、set,用var存储属性或者get、set计算属性去实现
    2. 协议中定义的get,用任何属性都可以实现

示例:

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

class Person : Drawable {
    var x: Int = 0
    let y: Int = 0
    func draw() {
        
    }
    subscript(index: Int) -> Int {
        set{}
        get{index}
    }
}

class Student: Drawable {
    var x: Int{
        get{10}
        set{/* 省略 */}
    }
    var y: Int{0}
    func draw() {
        
    }
    subscript(index: Int) -> Int {
        set{}
        get{index}
    }
}

static 、class

为了保证通用,协议中必须用static定义类型方法、类型属性、类型下标

mutating

  • 只有将协议中的实例方法标记为mutating
    才允许结构体、枚举的具体实现修改自身内存
    类的实现方法不用加mutating,枚举、结构体才需要加
class Car {
    var price : Double = 0
    var color : String = "white"
    
}
struct Person {
    var car = Car()
    var cars = [Car]()
    init() {
        cars.append(car)
    }
    func changeColor()  {
        self.car.color = "red"
    }
    mutating func addCar(_ newCar:Car)  {
        self.cars.append(newCar)
    }
}
var p = Person()
p.changeColor()
p.addCar(Car())
print(p.car.color)
print(p.cars.count)

init

  • 协议中还可以定义初始化器init
    非final类实现时必须加上required
  • 如果从协议中实现的初始化器,刚好是重写了父类的指定初始化器
    那么这个初始化器就必须同时加required、override
  • 协议中定义的 init?、init!,可以用init、init?、init!去实现
  • 协议中定义的init,可以用init、init!去实现

协议的继承

一个协议可以继承其他协议

协议组合

协议组合,可以包含1个类类型(最多一个)

protocol Livable {}

protocol Runnable {}

class Person {
    
}
//接收Person或其子类的实例
func fun0(obj:Person)  {
    
}
//接收同时遵守Livable、Runnable协议、并且是Person或者其子类的实例
func fun1(obj: Person & Livable & Runnable){}

CaseIterable 协议(了解)

  • 让枚举遵守CaseIterable协议,可以实现遍历枚举值

CustomStringConvertible 协议

  • 遵守CustomStringConvertible协议,可以自定义实例的打印字符串,类似于OC中的description
class Person : CustomStringConvertible {
    var description: String{
        return "Person_description"
    }
}
var p = Person()
print(p)//Person_description

Any、AnyObject

Swift提供了2中特殊类型:AnyAnyObject

  • Any : 可以代表任意类型(枚举、结构体、类,也包括函数类型)
  • AnyObject : 可以代表任意类类型(在协议后面写上:AnyObject代表只有类能遵守这个协议)

is、as?、as!、as

  • is 用来判断是否为某种类型
  • as 用来做强制类型转换
class Person : CustomStringConvertible {
    var name: String = "Jack"
    
    var description: String{
        return "Person_description"
    }
}
var stu: Any = 10
stu = Person()

if let n = (stu as? Person)?.name{
    print(n)
}else{
    print("stu is not Person")
}
var data = [Any]()
data.append(Int("123") as Any)

print(stu is Int)

print(stu is Person)

print(data)

【打印结果】

false
true
Jack
[Optional(123)]

X.self 、X.type、AnyClass

  • X.self 是一个元类型(metadata)的指针,metadata存放着类型相关信息

  • X.self 属于 X.type 类型

class Person {}
class Student: Person {}

var perType : Person.Type = Person.self
var stuType : Student.Type = Student.self
perType = Student.self

var anyType:AnyObject.Type = perType
anyType = stuType

public typealias AnyClsaa = AnyObject.Type
var anyType2:AnyClass = Person.self
anyType2 = Student.self

var typeObj = type(of: anyType2)
print(typeObj)//Student.Type

【元类型应用】

  • 元类类型使用初始化init()必须用required修饰
    类似:OC 中的 [[ViewController.class alloc] init];
class Animal {
   required init() {
        
    }
}
class Cat: Animal {}
class Dog: Animal {}
class Pig: Animal {}

func creat(_ clas : [Animal.Type]) -> [Animal] {
    var arr = [Animal]()
    for cls in clas {
        arr.append(cls.init())
    }
    return arr
}

print(creat([Cat.self,Dog.self,Pig.self]))

Self 类似于OC中的instancetype

  • Self 一般用作返回值类型,限定返回值跟方法调用者必须是同一类型(也可作为参数类型)
  • 如果Self 用在类中,要求返回时调用的初始化器必须是required
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。