何时在 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
我今天问一个问题,因为我今天有点迷路。它是关于 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