Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using a Type Variable in a Generic

Tags:

I have this question except for Swift. How do I use a Type variable in a generic?

I tried this:

func intType() -> Int.Type {     return Int.self }  func test() {     var t = self.intType()     var arr = Array<t>() // Error: "'t' is not a type". Uh... yeah, it is. } 

This didn't work either:

var arr = Array<t.Type>() // Error: "'t' is not a type" var arr = Array<t.self>() // Swift doesn't seem to even understand this syntax at all. 

Is there a way to do this? I get the feeling that Swift just doesn't support it and is giving me somewhat ambiguous error messages.

Edit: Here's a more complex example where the problem can't be circumvented using a generic function header. Of course it doesn't make sense, but I have a sensible use for this kind of functionality somewhere in my code and would rather post a clean example instead of my actual code:

func someTypes() -> [Any.Type] {     var ret = [Any.Type]()     for (var i = 0; i<rand()%10; i++) {         if (rand()%2 == 0){ ret.append(Int.self) }         else {ret.append(String.self) }     }     return ret }  func test() {     var ts = self.someTypes()      for t in ts {         var arr = Array<t>()     } } 
like image 376
sudo Avatar asked Jun 18 '15 01:06

sudo


People also ask

Can you declare a variable of a generic type?

Yes it is possible, but only for Functions, not any arbitrary variable. As you can see, it's the type itself, where you define generics and then you can make a variable of that type, which allows it to set the generic.

Can a generic can take any object data type?

Generics in Java is similar to templates in C++. The idea is to allow type (Integer, String, … etc and user defined types) to be a parameter to methods, classes and interfaces. For example, classes like HashSet, ArrayList, HashMap, etc use generics very well. We can use them for any type.

How do you create a variable for a generic type in Java?

It specifies the type parameters (also called type variables) T1, T2, ..., and Tn. To update the Box class to use generics, you create a generic type declaration by changing the code "public class Box" to "public class Box<T>". This introduces the type variable, T, that can be used anywhere inside the class.

Can dynamic type be used for generic?

Not really. You need to use reflection, basically. Generics are really aimed at static typing rather than types only known at execution time.


1 Answers

Swift's static typing means the type of a variable must be known at compile time.

In the context of a generic function func foo<T>() { ... }, T looks like a variable, but its type is actually known at compile time based on where the function is called from. The behavior of Array<T>() depends on T, but this information is known at compile time.

When using protocols, Swift employs dynamic dispatch, so you can write Array<MyProtocol>(), and the array simply stores references to things which implement MyProtocol — so when you get something out of the array, you have access to all functions/variables/typealiases required by MyProtocol.

But if t is actually a variable of kind Any.Type, Array<t>() is meaningless since its type is actually not known at compile time. (Since Array is a generic struct, the compiler needs know which type to use as the generic parameter, but this is not possible.)

I would recommend watching some videos from WWDC this year:

  • Protocol-Oriented Programming in Swift
  • Building Better Apps with Value Types in Swift

I found this slide particularly helpful for understanding protocols and dynamic dispatch:

like image 181
jtbandes Avatar answered Nov 14 '22 23:11

jtbandes