【问题标题】:Swift Cast Generics TypeSwift Cast 泛型类型
【发布时间】:2015-04-07 14:18:50
【问题描述】:

我正在尝试将泛型类型转换为其超类。

class Foo : NSObject {
}
class Test<T> {
    let value: T
    init(_ value: T) {
        self.value = value
    }
}

let c = Test(Foo())
let v = c as Test<AnyObject>

但是就行了

let v = c as Test<AnyObject>

我得到“Foo”与“AnyObject”不同

虽然我可以使用内置数组来做到这一点

let array1 = [Foo(), Foo()]
let array2 = array1 as [AnyObject]

【问题讨论】:

    标签: swift generics casting


    【解决方案1】:

    数组在 Swift 中是特殊的,以便能够具有这种行为。很遗憾,您将无法在自己的课程中复制它。

    要获得类似的行为,您可以为您的类型提供另一个 init 方法:

    class Test<T> {
        let value: T
        init(_ value: T) {
            self.value = value
        }
    
        init<U>(other: Test<U>) {
            // in Swift 1.2 you will need as! here
            self.value = other.value as T
        }
    }
    
    let c = Test(Foo())
    let v = Test<AnyObject>(other: c)  // this will work ok
    

    请注意,在您想要转换为不兼容类型的情况下,这是不安全的(即会在运行时断言)(并且替代方案,可失败的初始化程序也会有并发症)

    【讨论】:

    • 编辑了我的答案以匹配,但恐怕它仍然不起作用。泛型类型在 Swift 中并不是协变的。见this article。你永远不会知道,这可能会在未来的版本中改变(但不要指望它,这种差异给支持它的语言带来了痛苦的世界)
    • 您必须阐述“这种差异给支持它的语言带来了痛苦的世界”。我需要一篇博文。
    • @Rob 比如C#的6位数名声大神weigh in。该问题给出了经典的 C# 协变数组概率。当然,Swift 数组没有这个问题,它是值类型。但展示了如果不小心处理,将协方差扩展到引用类型可能会导致悲剧。
    • Swift 明智地将隐式提升到 Any* 当然是非法的,所以这通常不是问题(我确实很享受他在 Scala 中描述的乐趣;但是 [T] 也是协变的...... ) 但我认为“关于值类型”这一点非常重要,并且确实使许多问题消失了。 Swift 在值类型和引用类型之间有一些非常清晰的分界线,这很有帮助。 (但我并不反对这个问题是微妙而棘手的,最好是过于严格和过于宽松。)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-07-27
    • 1970-01-01
    • 2020-09-18
    • 1970-01-01
    相关资源
    最近更新 更多