iCediCe
iCediCe

Reputation: 1723

Instantiate collection without knowing concrete type

I have a class which is generic over a type T which conforms to the Collection protocol. Now I want to instantiate the collection without knowing the concrete type of the collection, is this possible?

class FileStore<T: Collection>{

   var collection: T

   init(){
      collection = T() // This will never work
   }

}

Upvotes: 0

Views: 40

Answers (1)

David Pasztor
David Pasztor

Reputation: 54735

Collection doesn't have init amongst its protocol requirements, so you cannot directly initialize a Collection instance. You have several solutions though. You can either restrict your generic type constraint to a type that does guarantee having an init (such as Array) or you can create your own protocol requiring init, make T require conformance to that protocol and extend all Collections that you want to be able to store to conform to your protocol.

The second approach is shown below:

protocol Initializable {
    init()
}

class FileStore<T: Collection> where T: Initializable {
    var collection: T

    init(){
        collection = T.init()
    }
}

// Extend the `Collection` conformant types
extension Array: Initializable {}
extension Dictionary: Initializable {}
extension Set: Initializable {}

// Create a FileStore
FileStore<Array<Int>>()
FileStore<[String:Int]>()
FileStore<Set<String>>()

Or depending on which exact types you want to be able to store, using the built-in RangeReplaceableCollection as your type constraint is even better. (Bear in mind that quite a few standard library types don't conform to RangeReplaceableCollection that do conform to Collection and have empty inits, such as Dictionary, Set, etc.).

class OtherFileStore<T: RangeReplaceableCollection> {
    var collection = T.init()
}

Upvotes: 2

Related Questions