Swift4语法极简手册 — Protocols

Swift4语法极简手册

第二十二章节:Protocols

Protocols

在Swift4中,Class,Enum,Struct都可以申明实现Protocols

Protocol Syntax

定义一个Protocol

1
2
3
protocol SomeProtocol {
// protocol definition goes here
}

实现Protocols

1
2
3
4
//可以实现0个或多个Protocol
struct SomeStructure: FirstProtocol, AnotherProtocol {
// structure definition goes here
}

Property Requirements

在Protocol中申明Porperty需求

1
2
3
4
5
6
//实现someProtocol接口的需要有这两个属性,并满足其get,set方法的需求
protocol SomeProtocol {
var mustBeSettable: Int { get set }
//如果只申明为get,则实现可以只有get,也可以有get及set
var doesNotNeedToBeSettable: Int { get }
}

也可以申明static properties

1
2
3
protocol AnotherProtocol {
static var someTypeProperty: Int { get set }
}

Method Requirements

在Protocol中申明Method需求

类方法

1
2
3
4
protocol SomeProtocol {
//实现者需要有someTypeMethod这个static方法
static func someTypeMethod()
}

定义普通方法

1
2
3
protocol RandomNumberGenerator {
func random() -> Double
}

Mutating方法

1
2
3
protocol Togglable {
mutating func toggle()
}

Mutating主要用于给struct,enum实现而定义,class也可以实现这样的protocol并且不需要在方法前加mutating

Init Method

1
2
3
4
5
6
7
8
9
10
protocol SomeProtocol {
init(someParameter: Int)
}
class SomeClass: SomeProtocol {
//需要加required
required init(someParameter: Int) {
// initializer implementation goes here
}
}

Protocols as Types

Protocols本身也可以当作Types使用

  • 可用作方法中的参数类型,返回值类型等
  • 可用作变量或常量的类型
  • 可用到数组等集合中的类型
1
2
3
4
5
6
7
8
9
10
11
12
protocol Saying {
func say()
}
class Person : Saying {
func say() {
print("人可以说话")
}
}
//protocol可以当作Type
var person:Saying = Person()
person.say()

Extension & Protocol

你可以给一个Class,Struct,或Enum添加Extension来新增实现某个protocol

1
2
3
4
5
6
7
8
9
10
protocol TextRepresentable {
var textualDescription: String { get }
}
//给Dice类新增extension来实现TextRepresentable
extension Dice: TextRepresentable {
var textualDescription: String {
return "A \(sides)-sided dice"
}
}

如果你的类已经实现了protocol中的方法,但没有申明实现此protocol协议,你可以这样

1
2
3
4
5
6
7
8
struct Hamster {
var name: String
var textualDescription: String {
return "A hamster named \(name)"
}
}
extension Hamster: TextRepresentable {}

Protocol Inheritance

protocol是可以继承的,而且可以多继承

1
2
3
protocol InheritingProtocol: SomeProtocol, AnotherProtocol {
// protocol definition goes here
}

如上,InheritingProtocol继承了了SomeProtocol与AnotherProtocol协议

因此,任何实现InheritingProtocol协议的Type同时需要实现SomeProtocolAnotherProtocol两个协议

Class-Only Protocols

也可以定义只能给Class 使用的Protocols

1
2
3
protocol SomeClassOnlyProtocol: AnyObject, SomeInheritedProtocol {
// class-only protocol definition goes here
}

如上代码所示,只要让SomeClassOnlyProtocol继承AnyObject就可以了,这样就只有class才能实现这个协议

AnyObject在这也是一个协议

Protocol Composition

如果你需要明确一个实例实现多个protocols时,使用Protocol Composition是最合适的

1
2
3
4
//参数celebrator需要同时实现Named与Aged两个协议
func wishHappyBirthday(to celebrator: Named & Aged) {
print("Happy birthday, \(celebrator.name), you're \(celebrator.age)!")
}

使用(&)联合 多个协议表示需要同时实现这些协议

Checking for Protocol Conformance

使用is,as?,as!来进行协议的检查

is 来检查是否实现了某个协议

as? 将实例转成某个协议,如果成功,则返回协议实例,失败返回nil

as! 强制转换,成功,返回协议实例,失败则runtime error

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
protocol Saying {
func say()
}
class Person : Saying {
func say() {
print("人可以说话")
}
}
var person:Saying = Person()
//true
let isSaying = person is Saying
let sayingPeople:Saying? = person as? Saying
let sayingOne:Saying = person as! Saying

Optional Protocol Requirements

Optional Protocol是与OC打交道是需要使用的到的,OC中的protocol是允许可选的

1
2
3
4
@objc protocol CounterDataSource {
@objc optional func increment(forCount count: Int) -> Int
@objc optional var fixedIncrement: Int { get }
}

如上代码所示:使用optional关键字,并加上@objc

这样的协议OC,Swift都可以使用

Protocol Extensions

Protocol本身也可以定义Extensions

1
2
3
4
5
extension RandomNumberGenerator {
func randomBool() -> Bool {
return random() > 0.5
}
}

如上,任何实现RandomNumberGenerator自动含有randomBool()方法;

  • 如果实现的类自己override了randomBool()方法,则调用时,调用实现类自己实现的
  • 如果实现类没有override,则调用协议extension的这个

Protocol本身不能有带实现的方法,但Protocol的Extensions可以