Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Generic class inheritance in Swift

I have the following class:

class BaseCache<T: Equatable>: NSObject {

    var allEntities = [T]()

    // MARK: - Append

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

Now I want to subclass it, but I get annoying error, that my type "does not conform to protocol 'Equatable'": enter image description here

It seems generics in Swift are real pain-in-the-ass.

like image 768
Andrey Gordeev Avatar asked Jan 05 '15 05:01

Andrey Gordeev


People also ask

Can generic class be inherited?

You cannot inherit a generic type. // class Derived20 : T {}// NO!

What is generic class in Swift?

Swift Generics allows us to create a single function and class (or any other types) that can be used with different data types. This helps us to reuse our code.

What is generic protocol in Swift?

Swift enables us to create generic types, protocols, and functions, that aren't tied to any specific concrete type — but can instead be used with any type that meets a given set of requirements.


1 Answers

Your class definition of TrackingCache is wrong. It repeats the generic parameter:

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

It should be left out:

class TrackingCache: BaseCache<AftershipTracking> { }

This triggers the underlying swift error Classes derived from generic classes must also be generic. You can work around this issue by specifying a type parameter that is required to be or inherit from AftershipTracking:

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

Full example:

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
like image 135
lassej Avatar answered Oct 15 '22 23:10

lassej