Swift 协议(Protocol)⑩
2020-08-04 本文已影响0人
Aliv丶Zz
协议可以用来定义方法、属性、下标的生命,协议可以被枚举、结构体、类遵守(多个协议之间用逗号,隔开)
- 协议中的方法不能有默认值
- 默认情况下,协议中的内容必须全部实现
- 协议中定义属性时必须用var关键字
- 实现协议时的属性权限不能小于协议中定义的属性权限
- 协议中定义get、set,用var存储属性或者get、set计算属性去实现
- 协议中定义的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中特殊类型:Any
、AnyObject
- 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
的