Tailwind CSSTailwind CSS
Home
  • Tailwind CSS 书籍目录
  • Vue 3 开发实战指南
  • React 和 Next.js 学习
  • TypeScript
  • React开发框架书籍大纲
  • Shadcn学习大纲
  • Swift 编程语言:从入门到进阶
  • SwiftUI 学习指南
  • 函数式编程大纲
  • Swift 异步编程语言
  • Swift 协议化编程
  • SwiftUI MVVM 开发模式
  • SwiftUI 图表开发书籍
  • SwiftData
  • ArkTS编程语言:从入门到精通
  • 仓颉编程语言:从入门到精通
  • 鸿蒙手机客户端开发实战
  • WPF书籍
  • C#开发书籍
learn
  • Java编程语言
  • Kotlin 编程入门与实战
  • /python/outline.html
  • AI Agent
  • MCP (Model Context Protocol) 应用指南
  • 深度学习
  • 深度学习
  • 强化学习: 理论与实践
  • 扩散模型书籍
  • Agentic AI for Everyone
langchain
Home
  • Tailwind CSS 书籍目录
  • Vue 3 开发实战指南
  • React 和 Next.js 学习
  • TypeScript
  • React开发框架书籍大纲
  • Shadcn学习大纲
  • Swift 编程语言:从入门到进阶
  • SwiftUI 学习指南
  • 函数式编程大纲
  • Swift 异步编程语言
  • Swift 协议化编程
  • SwiftUI MVVM 开发模式
  • SwiftUI 图表开发书籍
  • SwiftData
  • ArkTS编程语言:从入门到精通
  • 仓颉编程语言:从入门到精通
  • 鸿蒙手机客户端开发实战
  • WPF书籍
  • C#开发书籍
learn
  • Java编程语言
  • Kotlin 编程入门与实战
  • /python/outline.html
  • AI Agent
  • MCP (Model Context Protocol) 应用指南
  • 深度学习
  • 深度学习
  • 强化学习: 理论与实践
  • 扩散模型书籍
  • Agentic AI for Everyone
langchain
  • 协议的定义与实现

协议的定义与实现

在 Swift 中,协议(Protocol)是一种非常重要的特性,它定义了一组方法、属性和其他需求,供类、结构体或枚举去实现。协议并不提供具体的实现,而是指定了一个接口,任何遵循该协议的类型必须实现协议中定义的要求。通过协议,Swift 支持面向协议编程(Protocol-Oriented Programming),这使得代码更加灵活和可扩展。


1. 协议的定义

协议的定义是通过 protocol 关键字完成的。协议可以定义实例方法、类方法、属性等要求。协议本身不包含实现细节,遵循协议的类型必须提供具体的实现。

定义协议

协议定义的语法如下:

protocol SomeProtocol {
    var property: String { get set }
    func someMethod()
}

在这个协议中,SomeProtocol 定义了一个属性 property 和一个方法 someMethod。任何遵循 SomeProtocol 协议的类型都需要提供 property 的实现和 someMethod() 的具体实现。

协议的要求

协议可以规定属性的读写权限(get 或 get set),方法的可选性,以及其它要求。具体要求如下:

  • 属性要求:可以是只读属性(get)或可读写属性(get set)。
  • 方法要求:可以是实例方法或类方法。
  • 构造器要求:协议还可以要求某些构造器的实现。

协议示例

protocol Shape {
    var area: Double { get }
    func draw()
}

在上面的例子中,Shape 协议定义了一个只读属性 area 和一个方法 draw,任何符合 Shape 协议的类型都必须实现这两个要求。


2. 协议的实现

遵循协议的类、结构体或枚举必须实现协议中定义的所有要求。可以通过 :协议名 来声明某个类型遵循协议。

结构体遵循协议

struct Circle: Shape {
    var radius: Double

    var area: Double {
        return .pi * radius * radius
    }

    func draw() {
        print("Drawing a circle with radius \(radius).")
    }
}

let circle = Circle(radius: 5)
print(circle.area)  // 输出 78.53981633974483
circle.draw()  // 输出 "Drawing a circle with radius 5.0."

在这个例子中,Circle 结构体遵循了 Shape 协议,必须实现 area 和 draw() 方法。

类遵循协议

class Rectangle: Shape {
    var width: Double
    var height: Double

    init(width: Double, height: Double) {
        self.width = width
        self.height = height
    }

    var area: Double {
        return width * height
    }

    func draw() {
        print("Drawing a rectangle with width \(width) and height \(height).")
    }
}

let rectangle = Rectangle(width: 4, height: 6)
print(rectangle.area)  // 输出 24
rectangle.draw()  // 输出 "Drawing a rectangle with width 4.0 and height 6.0."

Rectangle 类也遵循了 Shape 协议,实现了 area 和 draw() 方法。


3. 协议的可选方法(协议扩展)

在 Swift 中,协议本身可以定义一些可选的方法,但只有通过协议扩展(Protocol Extension)来实现。这样,可以给协议提供默认的实现,减少需要在每个遵循协议的类型中重复代码。

协议扩展

protocol Shape {
    var area: Double { get }
    func draw()
    func describe() // 新增方法
}

extension Shape {
    func describe() {
        print("This is a shape with area \(area).")
    }
}

在这个例子中,Shape 协议扩展了一个 describe() 方法,给所有遵循协议的类型提供了默认实现。

遵循协议的类型使用协议扩展方法

struct Circle: Shape {
    var radius: Double

    var area: Double {
        return .pi * radius * radius
    }

    func draw() {
        print("Drawing a circle with radius \(radius).")
    }
}

let circle = Circle(radius: 5)
circle.describe()  // 输出 "This is a shape with area 78.53981633974483."

通过协议扩展,Circle 类型无需再实现 describe() 方法,它自动继承了协议扩展中的默认实现。


4. 协议的委托与关联类型

有时协议中的方法需要与特定的类型有关,Swift 提供了关联类型(Associated Types)来实现这一点。关联类型是协议中的占位符类型,它可以在遵循协议的类型中指定具体类型。

关联类型

protocol Container {
    associatedtype Item
    var items: [Item] { get set }
    mutating func addItem(_ item: Item)
}

struct StringContainer: Container {
    var items: [String] = []

    mutating func addItem(_ item: String) {
        items.append(item)
    }
}

var stringContainer = StringContainer()
stringContainer.addItem("Hello")
print(stringContainer.items)  // 输出 ["Hello"]

在这个例子中,Container 协议定义了一个关联类型 Item,用于表示容器内的元素类型。StringContainer 结构体遵循了该协议,并指定 Item 类型为 String。


5. 协议合成

Swift 允许将多个协议合并成一个新的协议。这种机制称为协议合成。通过协议合成,可以让一个类型遵循多个协议。

协议合成

protocol Shape {
    var area: Double { get }
}

protocol Drawable {
    func draw()
}

struct Circle: Shape, Drawable {
    var radius: Double

    var area: Double {
        return .pi * radius * radius
    }

    func draw() {
        print("Drawing a circle with radius \(radius).")
    }
}

func displayDetails(shape: Shape & Drawable) {
    print("Area: \(shape.area)")
    shape.draw()
}

let circle = Circle(radius: 5)
displayDetails(shape: circle)
// 输出:
// Area: 78.53981633974483
// Drawing a circle with radius 5.0

在这个例子中,Shape 和 Drawable 协议被合并到一个新的类型 Shape & Drawable 中,表示该类型需要同时符合这两个协议。


6. 总结

  • 协议的定义:协议定义了一组要求,类型必须遵循协议并实现这些要求。
  • 协议的实现:类、结构体或枚举通过 :协议名 来遵循协议,并提供具体的实现。
  • 协议扩展:协议可以通过扩展提供默认实现,减少每个遵循协议的类型中的重复代码。
  • 协议的关联类型:协议可以使用关联类型来定义与特定类型相关的需求。
  • 协议合成:多个协议可以通过合成形成一个新的协议,要求类型同时遵循多个协议。

协议在 Swift 中是一个非常强大的工具,它帮助我们实现了灵活的代码组织、复用和抽象,支持面向协议的编程理念,从而提高代码的可维护性和可扩展性。

Last Updated:: 12/1/24, 4:07 PM