何时在 Swift 中使用协议

When to use protocol in Swift

我今天问一个问题,因为我今天有点迷路。它是关于 Swift 和协议以及更多关于面向协议编程 (POP) 的内容。

我阅读了有关它的文章,甚至是一本书,但我仍然感到困惑。每个人似乎都在说 Protocol 是一个很棒的工具等等,但我真的不明白它的力量。

我有一个问题,因为我正在编写一个 class 体积,它是体积作为对象的表示。假设

struct Volume {
  var value: Float = 1
  var isLogScale: Bool = false
  var maxLogVolume: Float = 6.0 // value in dB
  var maxLinearVolume: Float = 1.0
  let dynamicRange: Float = 50.0


  func convertLinearToLog() -> Float {
    // Do some maths
  }

  func otherFunction() {
    print("Hello, I'm the most useless function in the world.")
  }
}

这是典型的class没什么特别的。

但是……我应该更好地使用这样的协议吗:

protocol VolumeProtocol {
  var value: Float {get set}
  var isLogScale: Bool {get set}
  var maxLogVolume: Float {get set}
  var maxLinearVolume: Float {get set}
  let dynamicRange: Float {get}

  func convertLinearToLog() -> Float
  func otherFunction()
}

然后重新实现一切,如

struct MyVolumeClass: VolumeProtocol {
// Same thing as before
}

我真的无法回答这个问题,所以如果你能帮助我什么时候使用协议,什么时候不使用协议,我将不胜感激。

协议有不止一个用例,但可以这样想:

  • 对于 classes,协议提供了一个独立于 class 层次结构的轻量级继承层次结构。给定一个 class 动物及其子 class 猫、狗、鸟和昆虫,您如何指定只有鸟和昆虫共享 fly 方法?

  • 对于结构,协议提供了一个继承层次结构,否则将完全丢失!结构没有上层结构。那么,给定一个 struct Bird 和一个 struct Insect,您将如何指定它们共享一个 fly 方法?

现在,您可以回答说 Bird 和 Insect 恰好有 fly 方法,故事到此结束。但是当你需要谈论集合 "all types that have a fly method" 时,这就不行了。当您希望编译器能够将 fly 方法发送给一个对象时,您 do 需要谈论该集合,因为它 一个 fly 方法。

解决方案是协议:

protocol Flier {
    func fly()
}

现在 Flier 是类型。在需要Flier的地方可以使用任何符合Flier的类型的实例,编译器会让你告诉任何Flier给fly,这样问题就解决了:

var myFlier : Flier = Bird() // if Bird conforms to Flier
myFlier.fly() // legal