Swift初学 - 四大自定义数据类型之Protocol
最后一个自定义的类型:protocol,这个就很像java的interface,protocol只能定义property和method的名字或参数类型这些,不能有实现代码;那些遵循这个protocol的class,struct或者enum必须实现这些定义好的property(get/set)和method。
一、定义和使用
protocol Person {
var name:String { get set }
associatedtype IdType
var identity: IdType { get }
init(name: String)
func job() -> String
}
定义了一个Person protocol,那么任何class或struct遵循Person的话,都必须要有name这个属性并且实现job这个方法:
class Student: Person {
var name: String
typealias IdType = String
var identity: String = "Student Card"
required init(name: String) {
self.name = name
}
func job() -> String {
return "\(name) is a student"
}
}
虽然很容易理解,但有些地方还是要注意的:
a) 我在Person定义name的时候,写了get和set,说明他是一个读写的属性,在Student里,name就一定要用var不能用let
b) 如果遵循的protocol里有init,那么实现的时候必须要用required init
c) protocol中的identity虽然逻辑有点牵强,但associatedtype就是为了在protocol中先声明一个自定义的类型(IdType),因为我们并不知道以后遵循这个protocol的identity是string还是Int还是什么;然后再Student的实现里我们就可以先用typealias把IdType明确为String,然后在给identity赋值
二、用extension来遵循protocol
如果我们想让第三方库中的一个class或struct也遵循我们定义的protocol,我们可以用extension来实现:
protocol MyString {
var length: Int { get }
}
extension String: MyString {
var length: Int {
return self.count
}
}
let str = "sdfsdfsd"
str.length // 8
三、一些常用的swift protocols
Swift中有很多protocols,我们为了自己方便,可以让自己的class或struct来遵循他们,下面就列举几个:
1、Equatable
我们知道两个class是不能用==好来比较的,但是我就是想用==号来比较他们一些属性,这样很方便。怎么实现呢?
extension Student: Equatable {
static func == (lhs: Student, rhs: Student) -> Bool {
return lhs.name == rhs.name
}
}
let me = Student(name: "joshua")
let you = Student(name: "dog")
let he = Student(name: "dasfsdfsd")
me == you //false
a) 你可以不用extension,直接在定义Student的时候就让他遵循Equatable;但是用extension更容易管理代码,哪天你不想遵循了,就删了这几行就行
b) 在xcode写下: Equatable,点一下Fix,他会自动给你补全==这个func的
2、Comparable
extension Student: Comparable {
static func < (lhs: Student, rhs: Student) -> Bool {
return lhs.name.count < rhs.name.count
}
}
me < you // false
有了Equatable和Comparable,swift有时候就可以自动比较Student这个类型了,比如
var arr = [me, you, he]
arr.sort() // [you, me, he]
非常方便!
3、Hashable
只有像String, Int这种struct才能当做dictionary的key,如果你想让class类型也能当key,那你就得遵循Hashable:
extension Student: Hashable {
static func == (lhs: Student, rhs: Student) -> Bool {
return lhs.name == rhs.name
}
func hash(into hasher: inout Hasher) {
hasher.combine(name)
}
}
var dict = [me: 1]
a) 如果我们已经遵循了Equatable,==这个func不写也行
b) hash这个func xcode好像不会帮你补全,你得自己写
c) hasher必须combine所有你在==号里包括的属性
4、CustomStringConvertible
这个可以用来debug:
extension Student: CustomStringConvertible {
var description: String {
return "My name is \(name)"
}
}
print(me) // My name is joshua