我在swift中解决了以下用例问题,并且不确定它是否可行。
假设我有一个使用泛型的数据结构类 - 让我们调用它
Container<T>
现在我有一个可以是不同类型T的许多Container的列表,例如
Container<A>, Container<B>, Container<A>, Container<C>, Container<C>, ...
我想通过列表,并为每个容器找出&#34;内部类型&#34;是。如果可能的话,我想加入它。
T的可能类型不是有限的,所以我不能对每个类型进行大的开关案例测试。
我尝试的是类似的东西:
if value is Container<???> { <- 1. should match Container with any type (??? stands here for any type)
let value = value as! Container<???> <- 2. a cast to the specific Container
...
}
有哪些方法可以解决1.和2.?
答案 0 :(得分:1)
您可以切换一个值,并有条件地将其转换为某些已知的可能类型(如果案例失败:类型转换成功)。
示例:
class MyClass : CustomStringConvertible {
var foo : Int = 1
var description: String { return "MyClass().foo = \(foo)"}
}
struct Container<T> {
var myVar : T
}
let value1 = Container<Int>(myVar: 1)
let value2 = Container<MyClass>(myVar: MyClass())
let value3 = Container<String>(myVar: "one")
let value4 = "Foobar"
let values : [Any] = [value1, value2, value3, value4]
for (i, value) in values.enumerate() {
switch value {
case let foo as Container<Int>:
print("Element #\(i+1) is an Int container with .myVar = \(foo.myVar)")
case let foo as Container<String>:
print("Element #\(i+1) is a String container with .myVar = \(foo.myVar)")
case let foo as Container<MyClass>:
print("Element #\(i+1) is a MyClass container with .myVar = \(foo.myVar)")
case _: print("Element #\(i+1) is of unknown type.")
}
}
/* Element #1 is an Int container with .myVar = 1
Element #2 is a MyClass container with .myVar = MyClass().foo = 1
Element #3 is a String container with .myVar = one
Element #4 is of unknown type. */
注意:就像我发布我的回答一样,我看到了你的编辑补充:
“T的可能类型不是有限的,所以我不能有一个大的 为每个人切换案例测试。“
所以你有一个“无限”数量的不同类型可能会保存在你的这个列表中?在这种情况下,我假设您没有自定义操作,具体取决于容器中的内容,在这种情况下,我不明白为什么您需要尝试向下转换(因为,根据您的更新,您可以总是向下倾斜到某些“无限”类型的数据。)
“我想通过列表,并为每个容器找出答案 什么是“内在类型”。如果可能的话,我想加入它。“
这相当于只找到容器类型并铸造成自己;后者将永远成功,并没有真正的目的。
因此,剩下的只是找出每个容器的泛型类型的值。你可以这样做,例如使用运行时内省。
设定:
/* Container and protocol setup */
class MyClass : CustomStringConvertible {
var foo : Int = 1
var description: String { return "MyClass().foo = \(foo)"}
}
protocol MyUniqueGenericContainer {
func printMyVar()
}
struct Container<T> : MyUniqueGenericContainer {
var myVar : T
// MARK: MyUniqueGenericContainer
func printMyVar() {
print(myVar)
}
}
使用运行时内省查找容器值类型并调用blueprinted方法printMyVar()
的示例:
let value1 = Container<Int>(myVar: 1)
let value2 = Container<MyClass>(myVar: MyClass())
let value3 = Container<String>(myVar: "one")
let value4 = "Foobar"
let values : [Any] = [value1, value2, value3, value4]
for (i, value) in values.enumerate() {
var isKnown = true
switch value {
case let val as MyUniqueGenericContainer:
let valueMirror = Mirror(reflecting: value).children.filter{ $0.label == "myVar" }
if let containerMyVar = valueMirror.first?.value {
let containerType = containerMyVar.dynamicType
print("Element #\(i+1) type: Container<\(containerType)>,",
".printMyVar(): ", terminator: "")
val.printMyVar()
}
else { isKnown = false }
case _ : isKnown = false
}
if !isKnown {
print("Element #\(i+1) not of Container<T> type")
}
}
打印:
/* Element #1 type: Container<Int>, .printMyVar(): 1
Element #2 type: Container<MyClass>, .printMyVar(): MyClass().foo = 1
Element #3 type: Container<String>, .printMyVar(): one
Element #4 not of Container<T> type */
答案 1 :(得分:0)
使用可选链接:
if let value = value as? ContainerA<XYZ> {
// value is now of type ContainerA<XYZ>
} else {
// can't cast
}
答案 2 :(得分:0)
你去......
switch value {
case is ContainerA<A>:
...
case is ContainerA<B>:
...
case is ContainerA<C>:
...
default:
...
}
或
if let value = value as? ContainerA<A> {
// value is now of type ContainerA<A>
} else if let value = value as? ContainerA<B> {
// value is now of type ContainerA<B>
} else if let value = value as? ContainerA<C> {
// value is now of type ContainerA<C>
} else {
// can't cast
}