假设存在协议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
}
}
想法会有所帮助。
答案 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。