协议Protocol
- 协议可以用来定义方法、属性、下标声明,协议可以被枚举、结构体、类遵守(多个协议用逗号隔开)
- 协议中定义方法适合不能有默认参数值
- 默认情况下,协议中定义的内容必须全部实现
- 协议中定义属性必须是
var
- 实现协议的属性权限要不小于协议中定义的属性权限
protocol Drawable {
func draw()
var x: Int { get set }
var y: Int { get }
subscript(index: Int) -> Int { get set }
}
protocol Test1 {}
protocol Test2 {}
protocol Test3 {}
class TestClass: Test1, Test2, Test3 { }
class Personal: Drawable {
var x: Int = 0
var y: Int = 0
func draw() {
print("Personal draw")
}
subscript(index: Int) -> Int {
get { index }
set { }
}
}
协议中的属性
protocol Drawable {
var x: Int { get set }
var y: Int { get }
}
协议Drawable
中定义了两个变量x
、y
,那么在其他对象中如何实现这两个属性,如果做到实现的时候让x
是可读可写的,让y
是只读的
- 用存储属性方式实现,
x
设置成变量,满足可读可写,y
设置成常量,满足只读
class Personal: Drawable {
var x: Int = 0
let y: Int = 0
}
- 用计算属性方式实现,计算属性有
get
、set
方法
class Personal: Drawable {
var x: Int {
get { 0 }
set { }
}
var y: Int {
get { 0 }
}
}
static、class
- 为了保证通用,协议中必须用
static
关键字定义类型方法、类型属性、类型下标
protocol Drawable {
static func draw()
}
//如果允许子类重写,就用class
class Personal: Drawable {
class func draw() {
print("Personal draw")
}
}
//如果不允许子类重写,就用static
class Personal: Drawable {
static func draw() {
print("Personal draw")
}
}
mutating
只有将协议中的实例方法标记为mutating
- 才允许结构体、枚举的具体实现修改自身内存
- 类在实现方法时候不需要加
mutating
,枚举、结构体才需要添加
protocol Drawable {
mutating func draw()
}
class Size: Drawable {
var width: Int = 0
func draw() {
width = 10
}
}
struct Point: Drawable {
var x: Int = 0
mutating func draw() {
x = 10
}
}
init
协议中还可以定义初始化器init
- 非
final
类实现时必须加上required
protocol Drawable {
init(x: Int, y: Int)
}
class Point: Drawable {
required init(x: Int, y: Int) { }
}
final class Size: Drawable {
init(x: Int, y: Int) { }
}
如果从协议实现的初始化器,刚好是重写了父类的指定初始化器
- 那么这个初始化必须同时加上
required
、override
protocol Livable {
init(age: Int)
}
class Person {
init(age: Int) { }
}
class Student: Person, Livable {
required override init(age: Int) {
super.init(age: age)
}
}
init、init?、init!
- 协议中定义的
init?
、init!
,可以用init
、init?
、init!
去实现 - 协议中定义的
init
,可以用init
、init!
去实现
protocol Readable {
init()
init?(age: Int)
init!(num: Int)
}
class Personal: Readable {
required init() { }
// required init!() { }
required init?(age: Int) { }
// required init!(age: Int) { }
// required init(age: Int) { }
required init!(num: Int) { }
// required init?(num: Int) { }
// required init(num: Int) { }
}
协议的继承
一个协议可以继承其他协议
protocol Runnable {
func run()
}
protocol Livable: Runnable {
func breath()
}
class Person: Livable {
func run() {}
func breath() {}
}
协议组合
协议组合,可以包含1个类类型(最多一个)
protocol Livable { }
protocol Runnable { }
class Personal { }
//接受Personal或者其子类的实例
func fn1(obj: Personal) { }
//接受遵守Livable协议的实例
func fn2(obj: Livable) { }
//接受同时遵守Runnable、Livable协议的实例
func fn3(obj: Livable & Runnable) { }
//接受同时遵守Runnable、Livable协议,并且是Personal或者其子类的实例
func fn4(obj: Personal & Livable & Runnable) { }
typealias RealPerson = Personal & Livable & Runnable
//接受同时遵守Runnable、Livable协议,并且是Personal或者其子类的实例
func fn(obj: RealPerson) { }
CaseInterable
让枚举遵守CaseInterable协议,可以实现遍历枚举值
enum Season: CaseIterable {
case spring, summer, autumn, winter
}
let seasons = Season.allCases
print(seasons) // [SwiftDDDDD.Season.spring, SwiftDDDDD.Season.summer, SwiftDDDDD.Season.autumn, SwiftDDDDD.Season.winter]
for season in seasons {
print(season)
} // spring summer autumn winter
CustomStringConvertible
遵守CustomStringConvertible
协议,可以自定义实例的打印字符串
必须实现
var description: String
class Car: CustomStringConvertible {
var name: String
var price: Double
init(name: String, price: Double) {
self.name = name
self.price = price
}
var description: String {
"name = \(name), price = \(price)"
}
}
var c = Car(name: "三轮车", price: 100.1)
print(c) // name = 三轮车, price = 100.1
Any、AnyObject
swift
提供了2种特殊的类型:Any
、AnyObject
-
Any
:可以代表任意类型(枚举、类、结构体、也包括函数类型) -
AnyObject
:可以代表任意类
类型(在协议后面写上:AnyObject
代表只有类能遵守这个协议)
举例子🌰1
protocol Runnable { }
class Personal: Runnable { }
struct Size: Runnable {}
protocol Runnable: AnyObject { }
class Personal: Runnable { }
//报错:Non-class type 'Size' cannot conform to class protocol 'Runnable'
struct Size: Runnable {}
举例子🌰2
var stu: Any = 10
stu = "jack"
stu = Student()
var stu: AnyObject = 10 //报错:Value of type 'Int' does not conform to specified type 'AnyObject'
stu = "jack" //报错:lue of type 'String' does not conform to 'AnyObject' in assignment
stu = Student()
举个例子🌰3:创建1个能存放任意类型的数组
var data = Array<Any>()
data.append(1)
data.append(3.14)
data.append(Person())
data.append("jack")
data.append({10})
data.append(true)
网友评论