0Pricing
Swift Academy · 课时

作为契约的协议

定义独立于类型的行为契约。

作为契约的协议 是 CoddyKit 上的免费 Swift Academy 课时。 这是第 1 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 Swift Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 Swift Academy 课程共包含 4 节课。

什么是协议

协议定义了一个蓝图,其中包含遵循该协议的类型必须实现的方法、属性和其他要求。它是一份契约:任何采用该协议的类型都承诺提供协议声明的全部内容。

protocol Greetable {
    var name: String { get }
    func greet() -> String
}

遵循协议

类型通过采用协议并提供每项要求来遵循协议。这里的结构体同时满足了 name 属性和 greet() 方法的要求。

protocol Greetable {
    var name: String { get }
    func greet() -> String
}

struct Person: Greetable {
    let name: String
    func greet() -> String { "Hello, I am " + name }
}

let p = Person(name: "Ada")
print(p.greet())

属性要求

协议会规定属性是否必须可读取({ get }),或必须既可读取又可设置({ get set })。存储属性或计算属性都可以满足仅要求读取的属性要求。

protocol Identifiable {
    var id: String { get }
}

struct User: Identifiable {
    let id: String
}

print(User(id: "u-1").id)

方法要求

方法要求会列出名称、参数和返回类型,但不包含方法体。遵循协议的类型负责提供具体实现。

protocol Shape {
    func area() -> Double
}

struct Square: Shape {
    let side: Double
    func area() -> Double { side * side }
}

print(Square(side: 3).area())

可变更要求

对于值类型,修改 self 的方法必须标记为 mutating。请使用 mutating 声明该要求,以便结构体能够满足它。

protocol Toggleable {
    mutating func toggle()
}

struct Switch: Toggleable {
    var isOn = false
    mutating func toggle() { isOn.toggle() }
}

var s = Switch()
s.toggle()
print(s.isOn)

将协议用作类型

协议是一等类型。您可以将它用于变量、参数和返回值,从而接受任何遵循该协议的值。

protocol Animal { func sound() -> String }
struct Dog: Animal { func sound() -> String { "Woof" } }
struct Cat: Animal { func sound() -> String { "Meow" } }

let animals: [Animal] = [Dog(), Cat()]
for a in animals { print(a.sound()) }

通过协议实现多态

调用协议方法时,会将调用分派到值背后的具体类型。这让您可以通过一份契约编写适用于多种类型的代码。

protocol Describable { func describe() -> String }
struct Book: Describable { let t: String; func describe() -> String { "Book: " + t } }
struct Film: Describable { let t: String; func describe() -> String { "Film: " + t } }

func show(_ d: Describable) { print(d.describe()) }
show(Book(t: "Swift"))
show(Film(t: "Inception"))

初始化器要求

协议可以要求初始化器。类必须将实现标记为 required,这样子类也必须提供该初始化器。

protocol FromInt {
    init(value: Int)
}

struct Wrapper: FromInt {
    let value: Int
    init(value: Int) { self.value = value }
}

print(Wrapper(value: 42).value)

协议继承

一个协议可以继承一个或多个其他协议,并在继承的要求之上增加额外要求。

protocol Named { var name: String { get } }
protocol Aged: Named { var age: Int { get } }

struct Member: Aged {
    let name: String
    let age: Int
}

let m = Member(name: "Lin", age: 30)
print(m.name, m.age)

仅限类的协议

使用 AnyObject 标记协议,可以将遵循协议的类型限制为类。这对于委托等需要引用语义的场景很有用。

protocol Counter: AnyObject {
    var count: Int { get set }
}

class Box: Counter {
    var count = 0
}

let b = Box()
b.count = 5
print(b.count)

检查是否遵循协议

使用 is 和 as?,可以在运行时测试某个值是否遵循协议。

protocol Flyer { func fly() }
struct Bird: Flyer { func fly() { print("flap") } }
struct Rock {}

let things: [Any] = [Bird(), Rock()]
for t in things {
    if let f = t as? Flyer { f.fly() } else { print("grounded") }
}

快速检查

测试您对协议要求的理解。

回顾

您已经学习了协议是一份契约:它声明属性、方法、可变更和初始化器要求,但不提供实现。类型通过满足每项要求来遵循协议;协议可以作为类型用于多态,可以继承其他协议,也可以使用 AnyObject 将遵循者限制为类。

常见问题解答

「作为契约的协议」课时是免费的吗?

是的 — 「作为契约的协议」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 Swift Academy 课程的其余内容,请升级到 CoddyKit PRO。 Swift Academy 课程共包含 4 节课。

「作为契约的协议」这节课中我会学到什么?

定义独立于类型的行为契约。 你通过在浏览器中直接运行的动手代码来练习 Swift Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。

学习 Swift Academy 需要有经验吗?

无需任何先前经验。CoddyKit 上的 Swift Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 1 节课,共 4 节。

「作为契约的协议」课时需要多长时间?

大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。

我能在这节 Swift Academy 课中编写并运行代码吗?

能。每节 Swift Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。

此课程中的所有课时

  1. 作为契约的协议
  2. 扩展中的默认实现
  3. 协议组合
  4. 条件一致性
← 返回 Swift Academy