协议和扩展

木木木大约 3 分钟iOSSwift语法

协议和扩展

协议 (Protocol)

协议是一种描述某物必须具有的属性和方法的方式。告诉Swift哪些类型使用该协议——这个过程被称为采用协议。 编写一个函数来接受具有id属性的东西,但我们并不关心使用哪种类型的数据。 首先创建一个Identifiable协议,该协议将要求所有符合要求的类型都有一个可以读取(“get”)或写入(“set”)的id字符串:

protocol Identifiable {
    var id: String { get set }
}

创建一个采用该协议的结构:

struct User: Identifiable {
    var id: String
}

编写一个接受任何Identifiable对象的displayID()函数:

func displayID(thing: Identifiable) {
    print("My ID is \(thing.id)")
}

协议继承

一个协议可以从另一个协议继承。与类不同,可以同时继承多个协议。

protocol Payable {
    func calculateWages() -> Int
}

protocol NeedsTraining {
    func study()
}

protocol HasVacation {
    func takeVacation(days: Int)
}

可以创建一个单一Employee协议,将他们聚集在一个协议中。可以使新类型符合单一协议,而不是三个单独的协议。

protocol Employee: Payable, NeedsTraining, HasVacation { }

扩展 (Extension)

扩展允许向现有类型添加方法,做最初不打算做的事情。 例如,为Int类型添加一个扩展,以便它有一个squared()方法,返回当前数字平方:

extension Int {
    func squared() -> Int {
        return self * self
    }
}

创建一个整数,调用squared()方法:

let number = 8
number.squared()

Swift不允许在扩展中添加存储的属性,因此必须使用计算属性。

extension Int {
    var isEven: Bool {
        return self % 2 == 0
    }
}

协议扩展

协议允许描述某物应该拥有哪些方法,但不提供里面的代码。 扩展允许在方法中提供代码,但不能同时将方法添加到许多类型中。 协议扩展解决了这两个问题:它们就像常规扩展,除了扩展像Int这样的特定类型,而是扩展整个协议,以便所有符合的类型都得到更改。 例如,这里有一个包含一些名称的数组和一个集合:

let pythons = ["Eric", "Graham", "John", "Michael", "Terry", "Terry"]
let beatles = Set(["John", "Paul", "George", "Ringo"])

Swift的数组和集合都符合一个名为Collection的协议,因此可以为该协议编写一个扩展,以添加一个summarize()方法来整齐地打印集合

extension Collection {
    func summarize() {
        print("There are \(count) of us:")

        for name in self {
            print(name)
        }
    }
}

Array和Set现在都有这个方法:

pythons.summarize()
beatles.summarize()

面向协议编程

协议扩展可以为自己的协议方法提供默认实现。这使得类型很容易符合协议,并允许一种称为“面向协议的编程”的技术——围绕协议和协议扩展制作代码。

首先,这是一个名为Identifiable的协议,它要求任何符合要求的类型具有id属性和identify()方法:

protocol Identifiable {
    var id: String { get set }
    func identify()
}

可以让每个符合要求的类型编写identify()方法,但协议扩展允许提供默认值:

extension Identifiable {
    func identify() {
        print("My ID is \(id).")
    }
}

现在,当创建一个符合Identifiable的类型时,会自动获得identify():

struct User: Identifiable {
    var id: String
}

let twostraws = User(id: "twostraws")
twostraws.identify()
上次编辑于:
贡献者: perhapsdone