How do I create an array of generics? Example:
struct Thing<Any> {
}
let intThing = Thing<Int>()
let stringThing = Thing<String>()
// This line doesn't compile
// Cannot convert value of type 'Thing<Int>' to expected type 'Thing'
let things: [Thing] = [intThing, stringThing]
How do I declare a generic of any type (something like Thing<?>
or Thing<Any>
)?
Here, [Int]() specifies that the empty array can only store integer data elements. Note: In Swift, we can create arrays of any data type like Int , String , etc.
The placeholder type T is used in the function declaration. It tells Swift that this function can find any item in any array, as long as the foundItem and items in the array are of the same type. This makes sense — you want to look for a T value in an array of T values.
Generics and Any are often used for similar purposes, yet they behave very differently. In languages without generics, you typically use a combination of Any and runtime programming, whereas generics are statically checked at compile time.
You can do this:let things: [Any] = [intThing, stringThing]
Thing
is not a valid type on it's own. Thing<String>
is a type and Thing<Int>
is an other type and you can't mix different type within an array.
Have you notice that even let things: [Thing]
doesn't compile?
I think that what you are probably trying to do would be better server with an enum with associated values.
struct MyStruct<T> {
let property: T
init(property: T) {
self.property = property
}
}
enum Thing {
case int(Int)
case string(String)
case intStruct(MyStruct<Int>)
}
// creation
let myInt = Thing.int(2)
let myString = Thing.string("string")
let myIntStruct = Thing.intStruct(MyStruct<Int>(property: 3))
// down side is that you need a 'case' clause to retrieve the data
switch myIntStruct {
case let .int(value):
print("have a int: \(value)")
case let .string(value):
print("have a string: \(value)")
case let.intStruct(value):
print("have a intStruct\(value)")
}
// An array of Thing
let things: [Thing] = [myInt, myString, myIntStruct]
nice article about advance enum trick here
In this file about wrapping Plist data into a single structure, there is the use of an enum for the EntityType.
You can associate anything to an enum value, but it needs to be a fully qualified type. So you can't use MyStruct because it is not fully qualified, you need to use MyStruct<Int>
to fully qualify. This means that you would need to create a case for every generic type you want to use with MyStruct.
That is as far as you can go with your generic approach.
I'm not sure what you are trying to do. But if you want to achieve some kind of polymorphism that relies on methods that operate on T
but don't use T
as input nor output you should make your Thing
implement a protocol and make an array of that protocol and call your polymorphic method on that protocol.
You can use an enum
enum Thing {
case Text(String)
case Integer(Int)
}
Now you can create a Thing containing a String or an Int
let thingWithText = Thing.Text("Hello world")
let thingWithInt = Thing.Integer(123)
And you can put them inside an array of Thing(s)
(no generics involved).
let things = [thingWithText, thingWithInt]
Finally you can process the values inside the array this way
things.forEach { (thing) -> () in
switch thing {
case .Text(let text): print(text)
case .Integer(let integer): print(integer)
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With