常用共享代码的方式有:继承、拓展和全局方法。今天笔者分享一种通过 Protocol 共享代码的技巧。
准备工作
我们先构建一个类,一个结构体和一个枚举。它们都有一个 String 类型的属性 name。而且它们都有一个叫 printName 的方法,可以用来输出 name。
class PersonClass {
let name = "David"
func printName(){
print(name)
}
}
struct PersonStruct {
let name = "David"
func printName(){
print(name)
}
}
enum PersonEnum {
var name: String {
return "David"
}
case someone
func printName() {
print(name)
}
}
因为 PersonClass , PersonStruct 和 PersonEnum 的 printName 方法所做的业务是一模一样的,所以把这方法抽离出来放在一个统一的地方,会更方便维护和拓展。
构建协议
我们先构建一个名为 PrintNameProtocol 的协议。在这个协议里我们定义一个 String 类型的接口 name。并在拓展中添加一个具体的实现方法 printName。
protocol PrintNameProtocol {
var name: String { get }
}
extension PrintNameProtocol {
func printName() {
print(name)
}
}
接着我们让 PersonClass,PersonStruct 和 PersonEnum 去实现这个协议。
class PersonClass: PrintNameProtocol {
let name = "David"
}
struct PersonStruct: PrintNameProtocol {
let name = "David"
}
enum PersonEnum: PrintNameProtocol {
var name: String {
return "David"
}
case someone
}
因为 PersonClass,PersonStruct 和 PersonEnum 都有 String 类型的属性 name,所以它们都是实现了 PrintNameProtocol 所定义的接口的。接着,我们删除 printName 方法,因为这个方法已经在 PrintNameProtocol 中实现了。
使用共享代码
接着我们初始化一个 personClass 类对象,一个personStruct 结构体和一个枚举 personEnum。并调用一下 printName 方法。
let personClass = PersonClass()
let personStruct = PersonStruct()
let personEnum = PersonEnum.someone
personClass.printName()
personStruct.printName()
personEnum.printName()
控制台输出:
David
David
David
拓展共享代码
下面我们再拓展一下 printName 这个方法。
extension PrintNameProtocol {
func printName() {
print("Hello! My name is \(name)")
}
}
重新运行代码后,控制台输出:
Hello! My name is David
Hello! My name is David
Hello! My name is David
小结
通过拓展协议,我们实现了在类、结构体和枚举中共享代码。这种方式比继承更为灵活和强大。这种共享的方式也方便我们去维护和拓展某些业务代码。