協(xié)議(Protocol)
1、協(xié)議可以用來定義方法翰绊、屬性佩谷、下標的聲明旁壮,協(xié)議可以被枚舉、結構體谐檀、類遵守(多個協(xié)議之間用逗號隔開)
protocol Drawable {
func draw()
var x: Int { get set }
var y: Int { get }
subscript(index: Int) -> Int { get set }
}
2抡谐、協(xié)議中定義方法時不能有默認參數值
3、默認情況下桐猬,協(xié)議中定義的內容必須全部都實現(xiàn)
協(xié)議中的屬性
1麦撵、協(xié)議中定義屬性時必須用var關鍵字
2、實現(xiàn)協(xié)議時屬性權限要不小于協(xié)議中定義的屬性權限
協(xié)議定義get溃肪、set免胃,用var存儲屬性或get、set計算屬性去實現(xiàn)
協(xié)議定義get惫撰,用任何屬性都可以實現(xiàn)
class Person: Drawable {
var x: Int = 0
let y: Int = 0
func draw() {
print("Person draw")
}
subscript(index: Int) -> Int {
set {}
get { index }
}
}
class Person: Drawable {
var x: Int {
get { 0 }
set {}
}
var y: Int {
get { 0 }
}
func draw() {
print("Person draw")
}
subscript(index: Int) -> Int {
set {}
get { index }
}
}
static羔沙、class
1、為了保證通用厨钻,協(xié)議中必須用static定義類型方法扼雏、類型屬性、類型下標
protocol Drawable {
static func draw()
}
class Person1: Drawable {
class func draw() {
print("Person1 draw")
}
}
class Person2: Drawable {
static func draw() {
print("Person2 draw")
}
}
mutating
1夯膀、只有將協(xié)議中的實例方法標記為mutating
才允許結構體诗充、枚舉的具體實現(xiàn)修改自身內存
類在實現(xiàn)方法時不用加mutating,枚舉棍郎、結構體才需要加mutating
protocol Drawable {
mutating func draw()
}
class Size: Drawable {
var width: Int = 0
func draw() {
width = 10
}
}
static Point: Drawable {
var x: Int = 0
mutating func draw() {
x = 10
}
}
init
1其障、協(xié)議里面還可以定義初始化器init
非final類實現(xiàn)時必須加上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) {
}
}
2、如果從協(xié)議實現(xiàn)的初始化器涂佃,剛好是重寫了父類的指定初始化器
那么這個初始化必須同時加required励翼、override
protocol Liveable {
init(age: Int)
}
class Person {
init(age: Int) {}
}
class Student: Person, Liveable {
required override init(age: Int) {
super.init(age: age)
}
}
init、init?辜荠、init!
1汽抚、協(xié)議中定義的init?、init!伯病,可以用init造烁、init?、init!去實現(xiàn)
2午笛、協(xié)議中定義的init惭蟋,可以用init、init!去實現(xiàn)
protocol Liveable {
init()
init?(age: Int)
init!(no: Int)
}
class Person: Liveable {
required init() {}
// required init!() {}
required init?(age: Int) {}
// required init!(age: Int) {}
// required init(age: Int) {}
required init!(no: Int) {}
// required init?(no: Int) {}
// required init(no: Int) {}
}
協(xié)議的繼承
1药磺、一個協(xié)議可以繼承其他協(xié)議
協(xié)議組合
1告组、協(xié)議組合,可以包含1個類類型(最多1個)
protocol Livable {}
protocol Runnable {}
class Person {}
//接收Person或者其子類的實例
func fn0(obj: Person) {}
//接收遵守Livable協(xié)議的實例
func fn1(obj: Livable) {}
//接收同時遵守Livable和Runnable協(xié)議的實例
func fn2(obj: Livable & Runnable) {}
//接收同時遵守Livable癌佩、Runnable協(xié)議木缝,并且是Person或者其子類的實例
func fn3(obj: Person & Livable & Runnable) {}
typealias RealPerson = Person & Livable & Runnable
func fn4(obj: RealPerson) {}
CaseIterable
1便锨、讓枚舉遵守CaseIterable協(xié)議,可以實現(xiàn)遍歷枚舉值
enum Season: CaseIterable {
case spring, summer, autumn, winter
}
let seasons = Season.allCases
print(seasons.count) // 4
for season in seasons {
print(season)
}
CustomStringConvertible
1我碟、遵守CustomStringConvertible協(xié)議放案,可以自定義實例的打印字符串
class Person: CustomStringConvertible {
var age: Int
var name: String
init(age: Int, name: String) {
self.age = age
self.name = name
}
var description: String {
"age = \(age), name = \(name)"
}
}
var p = Person(age: 10, name: "Jack")
print(p) // age = 10, name = Jack