Swift泛型:在运行时首先确定类型

5
我有一个关于Swift和泛型的问题。我想做的是获取一个具有泛型类型的对象。但我首先要在运行时知道类型。但为了快速到达重点。

新编辑的块:

也许我可以通过类名来实现?我有一个作为字符串的类名。我通过镜像得到它。我能用那个字符串创建一个泛型实例吗?

let classname: String = "ClassA"
let firstA: a<classname> = a<classname>()
//            ^^^^^^^^^      ^^^^^^^^^
//            what to put here???          

新编辑的块结束:

我有两个带有泛型类型的类:

这是我的类型必须实现的协议:

protocol ToImplement {
    func getTypeForKey(key: String) -> NSObject.Type
}

这是我用于第一个泛型类型的类:

class MyClass: ToImplement {
    func getTypeForKey(key: String) -> NSObject.Type {
        if key == "key1" {
            return UIView.self
        } 
        else {
            return UIButton.self
        }
    }
}

这是我的第一个带有泛型的类:

class a<T:ToImplement> {
    func doSomethingWith(obj: T) -> T {

        // the next part usually runs in an iteration and there can be
        // a lot of different types from the getTypeForKey and the number
        // of types is not known

        let type = obj.getTypeForKey("key1")
        let newA: a<type> = a<type>()       // how could I do this? To create a type I do not know at the moment because it is a return value of the Object obj?
        //          ^^^^      ^^^^
        //          what to put here???


        return obj
    }
}

并且这就是我如何使用它的方式:
let mycls: MyClass = MyClass()
let firstA: a<MyClass> = a<MyClass>()
firstA.doSomethingWith(mycls)

现在我的问题是:我能否通过函数返回的泛型类型来创建类a的实例?这是否可行?
如果不可能,那该如何使用另一个实例创建一个具有泛型类型的实例。类似于以下内容:
let someA: a<instance.type> = a<instance.type>()

谢谢您的帮助!
敬礼,
Artur
2个回答

1
let type = obj.getType

好的,所以type是一个NSObject.Type。由于NSObject提供了init(),因此您可以使用它来实例化这种类型。

let obj = type.init()  // obj is a NSObject (or subclass)
return obj

当然,如果getType()返回的实际类型没有实现init(),则在运行时会失败。
另一种选择是使用关联类型:
protocol ToImplement {
    typealias ObjType: NSObject
}

然后,您可以将其用作通用约束条件:
func makeAnObject<T: ToImplement>(obj: T) -> T.ObjType {
    return T.ObjType()
}

这基本上会得到相同的结果。

你好,感谢你的回答,但我认为那不是我需要的。假设我有一个名为Car、Bike和House的类,它们实现了ToImplement协议。MyClass返回其中一个类型,例如Car、Bike、House甚至是它自己(MyClass)。现在我想创建一个新的实例,其类型与返回的类型完全相同,但此时我不知道它的类型。也许像let newA = a<obj.getTypeForKey("key1")>()这样的东西。我知道这不正确,但这正是我要做的事情。 - Artur Hellmann

0
我最近也遇到了同样的问题。实现你所要求的方式似乎是列出所有已知的类型,并具体实例化泛型类。
if type(of:instance) == MyClass.self {
    let someA = a<MyClass>()
} // more blocks for other concrete implementations

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接