Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/swift/18.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/cocoa/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在Swift中何时使用协议_Swift_Cocoa_Swift Protocols - Fatal编程技术网

在Swift中何时使用协议

在Swift中何时使用协议,swift,cocoa,swift-protocols,Swift,Cocoa,Swift Protocols,我今天问了一个问题,因为我今天有点迷路了。它是关于Swift和协议的,更多的是关于面向协议的编程(POP) 我读过关于它的文章,甚至是一本书,但我仍然感到困惑。每个人似乎都说协议是一个伟大的工具等等,但我并不真正理解它的力量 我有一个问题,因为我正在编写一个类卷,它是卷作为对象的表示。比方说 struct Volume { var value: Float = 1 var isLogScale: Bool = false var maxLogVolume: Float = 6.0 /

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

我读过关于它的文章,甚至是一本书,但我仍然感到困惑。每个人似乎都说协议是一个伟大的工具等等,但我并不真正理解它的力量

我有一个问题,因为我正在编写一个类卷,它是卷作为对象的表示。比方说

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.")
  }
}
这是一门典型的课,没什么特别的

但是…我应该给我们一个这样的协议吗:

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
}

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

协议有多个用例,但请这样想:

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

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

现在,你可以回答鸟类和昆虫恰好有
fly
方法,这就是故事的结尾。但是,当您需要谈论集合“所有具有
fly
方法的类型”时,这就行不通了。当你希望编译器能够将
fly
方法发送到一个对象,因为它有一个
fly
方法时,你确实需要提到这个集合

解决方案是一个协议:

protocol Flier {
    func fly()
}
现在传单是一种类型。符合Flier的任何类型的实例都可以在需要Flier的地方使用,编译器将允许您告诉任何Flier飞
fly
,因此问题得到解决:

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

您应该使用结构而不是类。顺便说一句,值得一看@LeoDabus你完全正确。抱歉,我在这里对类/结构犯了一个错误。事实上,这个案例完全是一个结构。我编辑了我的问题。感谢您的链接,使用协议的一个可能场景是,当您想抽象出几个类的一些常用方法/属性,但您不想出于任何原因使用继承(例如您的类已经需要从另一个类继承)。对于您当前的实现,创建
VolumeProtocol
是没有意义的,因为我不认为您会有几个不同的类符合此协议。@DávidPászor感谢您的解释,这就是为什么我觉得我的案例不好的原因。事实上,协议可以被看作是一个大的超类,我们把它分割成一个小的超类。事实上,在我的例子中,它可能是符合先前协议的procotols
volume
audioFormat
和class
singleAudioPlayer
multipleAudioPlayer
。对我来说,这样做还是不自然的,因为编写带有声明的“协议”对我来说仍然是无用的(我只对委托模式使用了协议),但它有助于维护code@DEADBEEF您还可以在协议中定义函数的默认实现,这样协议就不仅仅是一个声明