Ken*_*ker 3 polymorphism protocols properties class swift
这是场景。我想要显示许多不同的视图,具体取决于我向用户显示的模型对象。所以我建立了一个协议,任何实现它的视图都可以被呈现。
class MyItem { /* some model properties */ }
protocol ItemView: class {
// some protocol methods (e.g. updateWithItem(), etc)
func setupItem(item: MyItem)
}
class SpecificItemView: UIView, ItemView { /* there will be multiple classes like this */
func setupItem(item: MyItem) {
// do item setup
}
}
class AnotherItemView: UIView, ItemView {
func setupItem(item: MyItem) {
// do DIFFERENT item setup
}
}
Run Code Online (Sandbox Code Playgroud)
然后,当我在视图控制器中使用它们时,我得到了一个 ItemView 类:
class MyViewController: UIViewController {
var itemView: ItemView? // could be a SpecificItemView or AnotherItemView
override func viewDidLoad() {
itemView?.setupItem(MyItem())
itemView?.removeFromSuperview() /* this line won't compile */
}
}
Run Code Online (Sandbox Code Playgroud)
除了最后一行,我尝试调用UIView
方法 ( removeFromSuperview
) 之外,一切正常。这并不奇怪,因为ItemView
与 没有关系UIView
。
在 Objective CI 中,将通过指定我的 itemView ivar 来解决这个问题,如下所示:
@property (nonatomic, strong) UIView<ItemView> *itemView;
Run Code Online (Sandbox Code Playgroud)
但我似乎找不到类似的 Swift 语法。我怀疑没有办法在 Swift 中使用这种模式。如何以 Swift 友好的方式实现可互换 UIView 类的总体目标?
到目前为止,我发现的一种巧妙的UIView
解决方案是将我调用的任何方法(例如removeFromSuperview
)添加到我的ItemView
协议中。
我从Maurice Kelly那里得到的另一个建议(不是关于 SO)是创建一个UIView
子类,实现ItemView
协议,并且SpecificItemView
和 都AnotherItemView
可以从该子类继承。你可以在这个要点中看到它的实现。虽然这解决了将类和协议封装在单一类型(例如)中的问题var itemView: ItemViewParentClass
,但它基本上使协议变得毫无意义,因为您现在在父类中实现所有协议的方法并在子类中覆盖它们。该解决方案的最大缺点是,当您在视图控制器中引用子类 ( SpecificItemView
) 的实例时,必须将它们转换为新的假设父类 ( )。ItemViewParentClass
小智 5
从 Swift 5 开始,可以通过将协议限制为仅应用于UIViews
. 为此,只需执行以下操作:
protocol ItemView: UIView {
func setupItem(item: MyItem)
}
Run Code Online (Sandbox Code Playgroud)
通过将此约束添加到您的协议中,swift 编译器识别为 an 的任何对象ItemView
也将具有UIView
其上可用的所有方法。
同样,如果非子UIView
类尝试实现该ItemView
协议,您的代码将无法编译。