在Swift中进行types转换

我正在写一个库,可以从JSONparsing键入的ID。 但是,我发现types化规则有点困惑。

例:

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 

为什么第一个types转换成功而第二个转换失败呢? NSString有什么神奇的东西,它不会跨越Swift-only类吗?

我正在使用XCode版本6.1(6A1030)(撰写本文时为最新版本)。

一般来说,如果你有一个类A→B→C的层次结构(C从Binheritance而来,B又inheritance自A),并且你有一个B的实例,你可以向上转换为A,但是你不能贬低为C.

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

请注意,多态性允许您使用variables上传和下载 – 也就是说,如果您将C的实例存储在typesA的variables中,则可以将该variables转换为B和C,因为它实际上包含C的一个实例。但是,如果variables包含B的一个实例,则可以向下转换为B,但不转向C.

在你的情况,而不是downcasting你应该专门化一个构造函数接受NSString ,但我怀疑,在这个特定的情况下, NSString不能这样做(没有NSString指定的初始化接受一个string作为参数)。 如果你能够做到这一点,那么你的代码将如下所示:

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

在那个时候你可以使用a AccountId或者NSString的实例

NSString有什么神奇的东西,它不会跨越Swift-only类吗?

是。 Swift的String类自动桥接到NSString ,反之亦然。 从文档 :

Swift在Stringtypes和NSString类之间自动桥接。 这意味着,在任何你使用NSString对象的地方,你都可以使用Swiftstringtypes,并获得两种types的好处 – 即stringtypes的插值和Swiftdevise的API以及NSString类的广泛function。 出于这个原因,你几乎不需要直接在你自己的代码中使用NSString类。 实际上,当Swift导入Objective-C API时,它将用Stringtypesreplace所有的NSStringtypes。 当您的Objective-C代码使用Swift类时,导入器会用导入的API中的NSStringreplace所有的Stringtypes。

为什么第一个types转换成功,而第二个转换失败呢?

由于StringNSString之间的强关系,编译器知道如何从一个转换到另一个。 另一方面,因为你的AccountId类是NSString一个更专门的版本,你不能从StringAccountId