栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 面试经验 > 面试问答

为什么[SomeStruct]无法转换为[Any]?

面试问答 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

为什么[SomeStruct]无法转换为[Any]?

Swift 3更新

从Swift 3(特别是Xpre 8 beta 6附带的内部版本)开始,集合类型现在可以在幕后执行,从值类型元素集合到抽象类型元素集合的转换。

这意味着现在将编译以下内容:

protocol SomeProtocol {}struct Foo : SomeProtocol {}let arrayOfFoo : [Foo] = []let arrayOfSomeProtocol : [SomeProtocol] = arrayOfFoolet arrayOfAny : [Any] = arrayOfFoo

迅捷前3

这一切都始于Swift中的泛型是不变的,而不是协变的。记住,这

[Type]
只是的语法糖
Array<Type>
,您可以抽象出数组并
Any
希望更好地看到问题。

protocol Foo {}struct Bar : Foo {}struct Container<T> {}var f = Container<Foo>()var b = Container<Bar>()f = b // error: cannot assign value of type 'Container<Bar>' to type 'Container<Foo>'

与类类似:

class Foo {}class Bar : Foo {}class Container<T> {}var f = Container<Foo>()var b = Container<Bar>()f = b // error: cannot assign value of type 'Container<Bar>' to type 'Container<Foo>'

Swift中的泛型根本不可能实现这种协变行为(向上转换)。在您的示例中,由于不变性,

Array<SomeStruct>
被视为完全不相关的类型
Array<Any>

但是,数组是该规则的例外–它们可以在后台默默地处理从子类类型到超类类型的转换。但是,在将具有值类型元素的数组转换为具有抽象类型元素(例如

[Any]
)的数组时,它们的作用不同。

为了解决这个问题,您必须执行自己的逐个元素转换(因为各个元素是协变的)。实现此目的的常用方法是使用

map(_:)

var fooArray : [Any] = []let barArray : [SomeStruct] = []// the 'as Any' isn't technically necessary as Swift can infer it,// but it shows what's happening herefooArray = barArray.map {$0 as Any}

避免在这里进行隐式“幕后”转换的一个好理由是由于Swift将抽象类型存储在内存中的方式。使用“现有容器”是为了将任意大小的值存储在固定的内存块中–这意味着可能会为无法容纳在该容器中的值进行昂贵的堆分配(仅允许引用要存储的内存)该容器)。

因此,由于数组在内存中的存储方式发生了重大变化,因此禁止隐式转换是非常合理的。这使程序员可以清楚地知道,他们必须转换数组的每个元素-
导致内存结构发生这种更改(可能非常昂贵)。

有关Swift如何与抽象类型一起工作的更多技术细节,请参阅关于主题的WWDC精彩演讲。有关Swift中类型差异的更多信息,请参见有关该主题的精彩博客文章。

最后,确保在下面看到@dfri关于数组可以隐式转换元素类型的其他情况的注释–即,当元素可桥接到Objective-C时,它们可以由数组隐式完成。



转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/568968.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号