【问题标题】:Typecasting in SwiftSwift 中的类型转换
【发布时间】:2014-11-24 02:48:12
【问题描述】:

我正在编写一个可以从 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 的类?

我使用的是 XCode 版本 6.1 (6A1030)(撰写本文时的最新版本)。

【问题讨论】:

    标签: ios types casting swift


    【解决方案1】:

    作为一般规则,如果您有一个层次结构的类 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,其中需要AccountIdNSString 的实例

    【讨论】:

    • 所以没有办法为NSString 执行此操作,或者我只能在AccountId 类中创建一个新的构造函数(与任何NSString 构造函数不同的参数)可以做到吗?有没有办法创建AccountId 类的实例?
    • 恐怕你不能。但是,我认为从 NSString 继承一个类只是为了提供不同的语义在我个人看来并不是一个好习惯——它仍然是一个没有附加值的字符串。我不知道您是否需要编译类型检查 - 如果不需要,您可以查看 typealias
    • 是的,我的目标是类型安全,就像newtypes。我一直在使用 typealiases 来解决这个问题。它们有助于提高可读性,但缺乏类型安全功能。感谢您的回答和建议。
    【解决方案2】:

    NSString 有什么神奇之处,它不会跨过纯 Swift 类吗?

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

    Swift 自动在 String 类型和 NSString 之间建立桥梁 班级。这意味着在任何你使用 NSString 对象的地方,你都可以 改用 Swift String 类型并获得两者的好处 types——String 类型的插值和 Swift 设计的 API 以及 NSString 类的广泛功能。为此,您应该 几乎从不需要在您自己的代码中直接使用 NSString 类。 事实上,当 Swift 导入 Objective-C API 时,它会替换所有 NSString 类型与 String 类型。当你的 Objective-C 代码使用 Swift 类,导入器将所有 String 类型替换为 导入 API 中的 NSString。

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

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

    【讨论】:

    • 感谢您的清晰回答。是否有可能通过在AccountId 类上提供智能构造函数来弥合这一差距?或者,正如@Antonio 指出的那样,NSString 子类几乎是不可能的吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-07-30
    • 1970-01-01
    相关资源
    最近更新 更多