我正在编写一个可以从 JSON 解析类型化 ID 的库。但是,我发现类型转换规则有点令人费解。
例子:
class AccountId : NSString { }
let json : AnyObject? = "user-1" // Returned by NSJSONSerialization.JSONObjectWithData
let s = json as? NSString // Succeeds, s == Some("user-1")
let a = json as? AccountId // Fails, a == nil
为什么第一个类型转换成功而第二个类型转换失败? NSString
有什么神奇之处,它不会交叉到 Swift-only 类吗?
我使用的是 XCode 版本 6.1 (6A1030)(撰写本文时最新版本)。
最佳答案
作为一般规则,如果您有类 A -> B -> C 的层次结构(C 继承自 B,而 B 又继承自 A),并且您有 B 的实例,则可以向上转型到 A,但你不能垂头丧气到 C。
原因是 C 可能会添加 B 中没有的属性,因此编译器或运行时将不知道如何初始化额外的数据,更不用说它也必须分配。
请注意,多态性允许您使用变量进行向上转型和向下转型 - 这意味着,如果您将 C 的实例存储在 A 类型的变量中,则可以将该变量转换为 B 和 C,因为它实际上包含一个实例C 的。但是如果变量包含 B 的实例,则可以向下转换为 B,但不能向下转换为 C。
在你的情况下,你应该专门化一个接受 NSString
的构造函数,而不是向下转换,但我怀疑在 NSString
的这种特定情况下,它无法完成(没有 NSString
指定接受字符串作为参数的初始化器)。如果您能够做到这一点,那么您的代码将如下所示:
var json: AnyObject? = "test"
if let string = json as? NSString {
let a = AccountId(string: string)
}
此时您可以使用 a
,其中需要 AccountId
或 NSString
的实例
关于ios - Swift 中的类型转换,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26104487/