Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Store type in variable to use like a type later

Tags:

generics

swift

I'm trying to store a type in a variable so that I can use it like a 1st class type later on.

class SomeModel {}

let someType = SomeModel.self
let array = Array<someType>()

In this case sure I could have done Array<SomeModel>() instead but I want to generalize it and let subclasses provide the value of someType.

However I get errors like someType isn't a type or use of undeclared type 'someType' on the last line.

like image 740
jamone Avatar asked May 05 '15 21:05

jamone


3 Answers

func someFunc<T>(model: T) -> Array<T> {
    let array = Array<T>()
    return array
}

let someType = SomeModel.self
let array = someFunc(someType())

Looks like this does what I want. The only drawback is that I have to create an instance of the desired type to pass. In this case its minimal overhead, but it just seems like a waste.

Another thing with using generics like this is it appears that the generic's possible types are computed at compile time, so at run time model.dynamicType doesn't necessarily match T. In most cases it will, but if you are doing any reflection driven stuff make sure to really check your use case well.

like image 161
jamone Avatar answered Nov 10 '22 14:11

jamone


If you need to store several type values in array, this works pretty well:

let array: [Any.Type] = [String.self, Int.self]
like image 20
Exey Panteleev Avatar answered Nov 10 '22 15:11

Exey Panteleev


These days, this can be more easily and adaptably achieved by using .Type on a class or protocol. Note that only functions available to that root class or protocol will be accessible however, so you should ensure that a required initialiser of some kind is defined. For example:

protocol MyClass {
   init(someValue: Int)
}

class MyWrapper {

   let myClassType: MyClass.Type

   init(classType: MyClass.Type) {
      self.myClassType = classType
   }

   func new(with value: Int) -> MyClassType {
      return MyClassType.init(someValue: value)
   }

}

You can now initialise this rather silly factory class with a specific class implementing the MyClass protocol and when you call the new() function with an integer value it will generate a new instance of that class and return it.

like image 4
Ash Avatar answered Nov 10 '22 15:11

Ash