gpt4 book ai didi

swift - Swift 中的类型强制问题

转载 作者:IT王子 更新时间:2023-10-29 05:43:23 25 4
gpt4 key购买 nike

编辑:这在 Swift 3 中工作得很好,我们现在应该都在使用它 :)


如果我有两个协议(protocol),XY 其中 Y 实现了 X,为什么我不能将 Y 的数组分配给类型为 [X]?

的变量

更奇怪的是,我可以将它一个一个地转换成一个 X 数组,并且编译正常。

protocol X { }

protocol Y: X { }

// Make a test array of Y
extension String: Y { }
let a: [Y] = [ "Hello" ]

// Make it into an array of X - this works absolutely fine
let b: [X] = [ a[0] as X ]

// Why won't this cast work?
let c: [X] = a as [X]

我认为如果 Y 做了 X 能做的所有事情,这个赋值应该没问题(是的,我丢失了一些类型信息,但它至少应该编译!)

有什么想法吗?

编辑:current answer指出如果您使用可变数组,这是一件危险的事情——我没有得到但现在做了 :) 但是,如果我的数组都是不可变的,为什么 Swift 不允许这种情况发生?即使 c 是一个可变数组(即 var c = a as [X]),为什么 Swift 不复制它,让 a 完好无损?

最佳答案

这行不通,因为它可能会产生一些问题。例如:

var squares: Array<Square> = Array<Square>()
(squares as [Shape]).append(Circle())

现在我们的正方形数组中有一个圆。我们不想要那样,所以编译器不允许我们这样做。在 Scala 等其他语言中,您可以将泛型指定为 covariant , contravariantinvariant .

如果 Swift 允许您使用协变 泛型和 Array<Square>将是 Array<Shape> 的子类型.

如果使用逆变 Array<Square>将是 Array<Shape> 的父类(super class)型 (!) .

但是当使用不变泛型时,两者的子类型都不是。

在你的情况下最简单的方法可能是这样的:

let c = a.map{$0 as X}

现在c类型为 [X] .

有关类型差异及其可能出现问题的原因的更多信息,请访问 this wiki page .

编辑: 来回反复之后,似乎真正的问题是,协议(protocol)允许默认实现,因此可能会导致问题。使用类时,您的代码将完美编译。以下是一些可能会导致协议(protocol)出现问题的代码:

protocol Shape {
func surfaceArea() -> Double
}

extension Shape {
func surfaceArea() -> Double {
return 0.0
}
}

protocol Circle : Shape {
func getRadius() -> Double
}

extension Circle {
func surfaceArea() -> Double {
return getRadius() * getRadius() * 3.14
}
}

现在,当我们在这两个协议(protocol)之间上行时,surfaceArea()方法返回不同的值,Swift 不允许。

用类而不是协议(protocol)尝试同样的事情,Swift 编译你当前的代码不会有任何问题。对我来说,这是 Swift 团队的一个奇怪决定,但我仍然认为最好的缓解方法是使用

let c = a.map{$0 as X}

关于swift - Swift 中的类型强制问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36576596/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com