swift - 返回动态通用类型

标签 swift generics

已在 Swift 4.1 中修复

下面描述的问题已在 Swift 4.1 中修复,请参阅 Hamish 的评论

问题

我在这段代码上遇到运行时错误:

class A: Decodable{
    let a: Int
}

class B: A{
    let b: Int = 1 // side problem 2: class B has no initializers. 
                   //Why? It conforms to Decodable right??
}

func getType() -> A.Type{
    return B.self
}

class Test: UIViewController{

    override func viewDidLoad() {
        super.viewDidLoad()
        let data = ["a": 100, "b": 200]
        let jsonData =  try! JSONSerialization.data(withJSONObject: data)
        let t =         try! JSONDecoder().decode(getType(), from: jsonData)
        print((t as! B).b) //run-time
    }
}

因为t不是B。奇怪,我返回一个B.self。如果我打印 getType(),我得到这个:MyProject.B,所以尽管在我的方法签名中我返回了一个 A.Type,但它应该是一个 B.type,因为我的打印声明是这样说的。

当我删除调用 getType() 并直接放置 B.self 时,我得到完全相同的打印值。而且我没有遇到运行时错误。

这两种方式有什么区别?为什么我直接键入 B.self 的方式 2 可以工作,而我的第一种方式却不行,尽管打印语句中的值表明方式 1 和方式 2 的值相同。

最佳答案

JSONDecoder.decode() 是一个泛型函数,泛型在运行时得到解析。这意味着未使用 getType() 的运行时行为,编译器仅依赖于函数声明。

顺便说一句,Decodable 需要一个具体的类型来处理,一个在编译时选择的类型,因为它需要知道要使用哪个解码容器。

如果您对类型进行一些静态处理,您可以获得一些动态行为:

func decode(from data: Data, type: A.Type) throws {
    let decoder = JSONDecoder()
    if type == A.self { return try decoder.decode(data, type: A.self) }
    else if type == B.self { return try decoder.decode(data, type: B.self) }
    else { throw TypeNotSupportedError }
}

基本上在某些时候你需要给解码器一个具体的类型。

关于错误 #2,似乎编译器自动生成的 Codable 仅支持一个层次结构级别。

关于swift - 返回动态通用类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49499122/

相关文章:

swift - 静态变量被视为 let 常量?

c# - 返回未指定类型的泛型

swift - SWIFT 中的 continue、break、fall-through、throw 和 return 之间有什么区别?

swift - 更新部分背景颜色而不刷新整个 UITableView

java - 简单的Java泛型问题

java - 如何组合这些 Set<?为我的 API 扩展 Vector> 过滤函数?

ios - 将泛型应用于变量和函数 - Swift

android - Kotlin - 检查泛型参数是否可选?

ios - 如何在手机上访问电脑文件

ios - 异步函数返回正常,但数组变为空