Swift

时间:2016-02-21 09:53:24

标签: ios swift protocols

假设存在协议Draggable,通常将由UIView对象进行协调

protocol Draggable {
  drag()
}

我们可以在协议扩展中实现drag() option 1

// option 1
extension Draggable where Self: UIView {
  func drag() {
    // implementation
  }
}
extension UIView: Draggable {} // added after @Rich Tolley's answer

或者我们可以在drag()扩展名中UIView实施option 2

// option 2
extension UIView: Draggable {
  func drag() {
    // implementation
  }
}

这是我的问题:

  • 这两种方法之间是否存在差异(选项1和选项2)?
  • 如果是,那么我们设计项目或图书馆的区别是什么以及如何选择?

想法会有所帮助。

2 个答案:

答案 0 :(得分:8)

是的,存在差异:(编辑:或者至少在此q的原始版本中,没有将extension UIView : Draggable {}添加到选项1的末尾。)

  • 选项1为符合UIView的{​​{1}}实例创建默认实现。您仍然需要在声明Draggable中标记您希望与UIView一致的Draggable。任何符合class MyView : Draggable但不是Draggable子类的东西都需要提供自己的实现。

  • 选项2扩展所有 UIView以使其符合UIView。除非为这些类编写单独的扩展,否则其他任何内容都不能是Draggable,或者它们是手动符合协议的。无需在类声明中添加Draggable

协议扩展通常是更好的选择。在这种情况下,这显然是正确的,因为并非所有Draggable都可以是UIView。此外,关闭协议扩展路由意味着您可以创建一个Draggable对象,如果有必要,可以创建Draggable子类(不可否认,因为大多数Cocoa控件都是UIView子类 - 虽然不是全部 - UIView不是,但奇怪的是)

如果你遵循选项2,你将在很多情况下向UIBarButtonItem添加不必要的方法,这违反了良好的面向对象设计 - 特别是接口隔离原则(客户不应该被迫依赖关于他们不使用的方法 ) - 这是'我'在SOLID principles

答案 1 :(得分:3)

如果要为多个类实现功能,则应使用协议扩展。 在这种情况下,您应该使用extension UIView: Draggable,因为Implementation特定于UIView类。

假设您有一个提供位置的协议:

protocol Location {
    var location: CGPoint { get set }
}

并且您希望每个实现Location的类都符合Draggable,然后可以使用协议扩展:

extension Draggable where Self: Location {
    func drag() {
    }
}

如需进一步参考,请查看2015 WWDC的Protocol-Oriented Programming in Swift