【问题标题】:Generic class inheritance in SwiftSwift 中的泛型类继承
【发布时间】:2015-01-05 05:19:36
【问题描述】:

我有以下课程:

class BaseCache<T: Equatable>: NSObject {

    var allEntities = [T]()

    // MARK: - Append

    func appendEntities(newEntities: [T]) {
        ....
    }
}

现在我想对它进行子类化,但我收到烦人的错误,我的类型“不符合协议'Equatable'”:

似乎 Swift 中的泛型确实让人头疼。

【问题讨论】:

  • 在类定义中添加协议可能更容易。 class Aftership : Equatable { }
  • 这是不可能的,因为 Aftership SDK 是用 Objective C 编写的
  • 也许将 == 函数放在扩展中,这样它实际上符合协议。
  • == func 必须是全局的,所以它必须在扩展定义之外。实际上,AftershipTracking 符合 Equatable 协议,否则我会在扩展行上收到编译器警告。
  • 看起来你必须完全跳过泛型。我真的很讨厌 swift 泛型的一些限制。

标签: ios generics inheritance swift


【解决方案1】:

您对TrackingCache 的类定义是错误的。它重复了泛型参数:

class TrackingCache<AftershipTracking>: BaseCache<AftershipTracking> { }

应该省略:

class TrackingCache: BaseCache<AftershipTracking> { }

这会触发底层 swift 错误 Classes derived from generic classes must also be generic。您可以通过指定需要为 AftershipTracking 或继承自 AftershipTracking 的类型参数来解决此问题:

class TrackingCache<T: AftershipTracking>: BaseCache<AftershipTracking> { }

完整示例:

class BaseCache<T: Equatable>: NSObject {
  var items: [T] = []

  func appendItems( items: [T]) {
    self.items += items
    didAppendItems()
  }

  func didAppendItems() {} // for overriding
}

class AftershipTracking: NSObject {
  var identifier: Int
  init( identifier: Int) {
    self.identifier = identifier
    super.init()
  }
}

extension AftershipTracking: Equatable { }

func ==( lhs: AftershipTracking, rhs: AftershipTracking) -> Bool {
  return lhs.identifier == rhs.identifier
}

class TrackingCache<T: AftershipTracking>: BaseCache<AftershipTracking> {
  override func didAppendItems() {
    // do something
  }
}

let a = TrackingCache<AftershipTracking>()
let b = TrackingCache<AftershipTracking>()

a.appendItems( [AftershipTracking( identifier: 1)])
b.appendItems( [AftershipTracking( identifier: 1)])

let result = a.items == b.items // true

【讨论】:

  • 感谢您的回答,但我已经尝试过了,但没有成功。如果我将我的类定义为 class TrackingCache&lt;T: AftershipTracking&gt;: BaseCache&lt;AftershipTracking&gt;,我会在每个 override func 行上收到错误“方法不会覆盖其超类中的任何方法”。
  • 是的,但这是另一个问题。您的 BaseCache 类派生自 NSObject 以外的其他东西,对吗?一旦你从 Objective-C 类派生了一个泛型类,派生的 swift 类就看不到超方法了。您可以通过在 swift 中引入中间非泛型子类来解决此问题。但这确实是一个单独的问题。我的答案是您问题的正确解决方案。
  • BaseCache 直接派生自 NSObject,如上所述。即使我删除了 NSObject,也不会改变任何东西
  • 如果您尝试覆盖的方法在其参数列表中具有泛型类型,它将是不同的方法:appendItems( items: [Equatable])appendItems( items: [AftershipTracking]) 不同。不过,您仍然可以调用超方法。我将更新示例。
  • 谢谢,这解决了上一个问题,但又给出了另一个问题。当我尝试调用appendEntities 方法时,出现错误:Ambiguous use of 'appendEntities'。我不明白为什么编译器认为AfterTrackingT 是不同的类型——这就是问题所在
【解决方案2】:

这应该有效:

class TrackingCache<T: AftershipTracking>: BaseCache<T>

另一个例子:

protocol P {

}

class C: P {

}

class CS: C {

}

class L<T:P> {
    let c: T

    init(_ c: T) {
        self.c = c
    }
}

class LS<T:CS>:L<T> {

}

let i = LS(CS())

i.c

c 现在是CS

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-01-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-09-27
    相关资源
    最近更新 更多