【问题标题】:How to override instance method from protocol extension in Swift? [duplicate]如何从 Swift 中的协议扩展中覆盖实例方法? [复制]
【发布时间】:2016-07-26 22:12:30
【问题描述】:

我正在尝试从协议扩展中覆盖实例方法,但遇到了一些麻烦。

就上下文而言,我正在制作一个带有许多不同 UICollectionViews 的 iOS 应用程序。这些视图从不同的数据库中获取数据(需要不同的回调函数)并且具有非常不同的布局。因为(数据库、布局)的任何组合都是可能的,所以很难在没有大量代码重复的情况下创建一个漂亮的 OOP 类层次结构。

我的想法是将布局功能(主要是在 UICollectionViewDelegateFlowLayout 协议中定义的那些)放入协议扩展中,因此我可以使用扩展以实现所有相关布局功能的协议来装饰给定的 UICollectionView 子类,但我有很难过。问题的实质包含在下面的代码中。

class Base {
    func speak(){
        print("Base")
    }
}

class SubA: Base, ProtocolA {}

class SubB: Base, MyProtocolB {}

protocol MyProtocolA{
    func speak()
}

protocol MyProtocolB{
    func speak()
}

extension MyProtocolA{
    func speak(){
        print("A")        
    }
}

extension MyProtocolA{
    func speak(){
        print("B")        
    }
}

let suba = SubA()
suba.speak()  // prints "Base", I want it to print "A"

let subb = SubB()
subb.speak()  // prints "Base", I want it to print "B"

想法?

【问题讨论】:

  • “我的想法是将布局函数(主要是那些在 UICollectionViewDelegateFlowLayout 协议中定义的函数)放入协议扩展” 忘记这个想法。 Objective-C 永远不会从协议扩展调用实现,因为 Objective-C 不能看到协议扩展。这是 Swift 独有的功能。
  • @matt 这个问题不是关于 Obj-C 的,不是吗?
  • @TimVermeulen 是的。这是关于 Swift 协议扩展中的 Objective-C 委托方法。

标签: ios swift protocols swift-protocols swift-extensions


【解决方案1】:

仅当符合这些协议的类本身没有实现该方法时,才会调用协议中的默认实现。类的方法会覆盖协议的默认实现,而不是相反。

通常,您会执行以下操作:

protocol MyProtocolA {
    func speak()
}

protocol MyProtocolB {
    func speak()
}

extension MyProtocolA {
    func speak() {
        print("A")        
    }
}

extension MyProtocolB {
    func speak() {
        print("B")        
    }
}

class SubA: MyProtocolA {}

class SubB: MyProtocolB {}

let suba = SubA()
suba.speak()  // prints "A"

let subb = SubB()
subb.speak()  // prints "B"

如果你这样做了

class SubC: MyProtocolA {
    func speak (){
        print("C")
    }
}

let subc = SubC()
subc.speak()  // prints "C"

坦率地说,正如您所看到的,在此示例中使用 Base 完全是多余的,因此我已将其删除。显然,如果您出于其他原因需要从 Base 子类化,请随意。但关键是协议默认实现不会覆盖类的实现,而是相反。

【讨论】:

  • 很好的答案,谢谢 Rob。跟进:如果没有代码重用,这将如何实现?我所说的“这个”是指像我们这里的任何 2 变量混合和匹配场景(其中任何子类都需要基于其数据库和布局来实现功能)。该功能不适合分层结构。
  • 我没有关注你。你能举一个实际的例子来说明你的意思吗?
  • 所以我的应用程序具有 UICollectionViews,a) 具有各种布局,b) 从不同的数据库中获取数据。更具体地说,我有一个“图标”布局和“细节”布局,每个布局都覆盖了 cellForItemAtIndexPath 和许多 UICollectionViewDelegateFlowLayout 方法。但是我也有两个数据库,根据 CollectionView 从哪个数据库获取数据,需要不同的代码。所以 {Database 1, Database2} x {Icon, Detail} 的任何组合都需要它自己的子类。但是如果没有代码重复,你就无法真正做到这一点
猜你喜欢
  • 2015-10-04
  • 1970-01-01
  • 1970-01-01
  • 2018-09-04
  • 1970-01-01
  • 2017-05-11
  • 2016-11-07
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多