在Swift中进行类型转换

时间:2014-09-29 16:24:25

标签: ios types casting swift

我正在编写一个可以从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)(撰写本文时的最新版本)。

2 个答案:

答案 0 :(得分:22)

作为一般规则,如果您有A - >类的层次结构。 B - > C(C继承自B,后者继承自A),并且你有一个B的实例,你可以向上转换为A,但你不能向下转换为C.

原因是C可能会添加B中不可用的属性,因此编译器或运行时将不知道如何初始化其他数据,更不用说还必须分配它。

请注意,polymorphism允许你使用变量进行upcast和downcast - 这意味着,如果你有一个存储在A类变量中的C实例,你可以将该变量强制转换为B和C,因为它实际上包含一个实例但是如果变量包含B的实例,则可以向下转换为B,但不能向下转换为C.

在您的情况下,您应该专注于接受NSString的构造函数,而不是向下转换,但我怀疑在NSString的特定情况下,它无法完成(没有NSString指定的初始值设定项接受一个字符串作为参数)。如果您能够这样做,那么您的代码将如下所示:

var json: AnyObject? = "test"
if let string = json as? NSString {
    let a = AccountId(string: string)
}

此时您可以a使用AccountIdNSString的实例

答案 1 :(得分:1)

  

NSString是否有一些神奇的东西不会与仅限Swift的类交叉?

是。 Swift的String课程自动桥接到NSString,反之亦然。来自the docs

  

Swift自动在String类型和NSString之间架起桥梁   类。这意味着您可以在任何地方使用NSString对象   使用Swift String类型代替并获得两者的好处   types- String类型的插值和Swift设计的API和   NSString类的广泛功能。出于这个原因,你应该   几乎从不需要在您自己的代码中直接使用NSString类。   事实上,当Swift导入Objective-C API时,它取代了所有的   具有String类型的NSString类型。当您的Objective-C代码使用   Swift类,导入器替换所有的String类型   导入API中的NSString。

     

为什么第一个类型转换成功而第二个类型转换失败?

由于StringNSString之间的关系很强,编译器知道如何从一个转换为另一个。另一方面,由于您的AccountId课程是NSString的更专业版,因此​​您无法从String投射到AccountId