3 回答

TA貢獻(xiàn)1821條經(jīng)驗(yàn) 獲得超5個(gè)贊
Swift 3更新
從Swift 3(特別是Xcode 8 beta 6附帶的內(nèi)部版本)開始,集合類型現(xiàn)在可以在幕后執(zhí)行,從值類型元素集合到抽象類型元素集合的轉(zhuǎn)換。
這意味著現(xiàn)在將編譯以下內(nèi)容:
protocol SomeProtocol {}
struct Foo : SomeProtocol {}
let arrayOfFoo : [Foo] = []
let arrayOfSomeProtocol : [SomeProtocol] = arrayOfFoo
let arrayOfAny : [Any] = arrayOfFoo
迅捷前3
這一切都始于Swift中的泛型是不變的,而不是協(xié)變的。記住,這[Type]只是的語法糖Array<Type>,您可以抽象出數(shù)組并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中的泛型根本不可能實(shí)現(xiàn)這種協(xié)變行為(向上轉(zhuǎn)換)。在您的示例中,由于不變性,Array<SomeStruct>被視為完全不相關(guān)的類型Array<Any>。
但是,數(shù)組是該規(guī)則的例外–它們可以在后臺(tái)默默地處理從子類類型到超類類型的轉(zhuǎn)換。但是,在將具有值類型元素的數(shù)組轉(zhuǎn)換為具有抽象類型元素(例如[Any])的數(shù)組時(shí),它們的作用不同。
為了解決這個(gè)問題,您必須執(zhí)行自己的逐個(gè)元素轉(zhuǎn)換(因?yàn)楦鱾€(gè)元素是協(xié)變的)。實(shí)現(xiàn)此目的的常用方法是使用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 here
fooArray = barArray.map {$0 as Any}
在這里避免隱式“幕后”轉(zhuǎn)換的一個(gè)很好的理由是由于Swift將抽象類型存儲(chǔ)在內(nèi)存中的方式。使用“現(xiàn)有容器”是為了將任意大小的值存儲(chǔ)在固定的內(nèi)存塊中–這意味著可能會(huì)為無法容納在該容器中的值進(jìn)行昂貴的堆分配(僅允許引用要存儲(chǔ)在其中的內(nèi)存)該容器)。
因此,由于數(shù)組現(xiàn)在在內(nèi)存中的存儲(chǔ)方式發(fā)生了重大變化,因此禁止隱式轉(zhuǎn)換是很合理的。這使程序員可以清楚地知道,他們必須轉(zhuǎn)換數(shù)組的每個(gè)元素-導(dǎo)致內(nèi)存結(jié)構(gòu)發(fā)生這種更改(可能非常昂貴)。
有關(guān)Swift如何與抽象類型一起工作的更多技術(shù)細(xì)節(jié),請(qǐng)參閱關(guān)于主題的WWDC精彩演講。有關(guān)Swift中類型差異的更多信息,請(qǐng)參見有關(guān)該主題的精彩博客文章。
最后,請(qǐng)確保在下面看到@dfri關(guān)于數(shù)組可以隱式轉(zhuǎn)換元素類型的其他情況的注釋 –即,當(dāng)元素可橋接到Objective-C時(shí),它們可以由數(shù)組隱式完成。

TA貢獻(xiàn)1942條經(jīng)驗(yàn) 獲得超3個(gè)贊
Swift無法自動(dòng)在包含值類型和引用類型的數(shù)組之間進(jìn)行轉(zhuǎn)換。只需將數(shù)組映射到所需的類型即可:
fooArray = barArray.map({$ 0})//是否編譯

TA貢獻(xiàn)1886條經(jīng)驗(yàn) 獲得超2個(gè)贊
由于您提到了從子類類型(和實(shí)例)的數(shù)組到超類類型的數(shù)組的轉(zhuǎn)換的例外,因此我可能要添加一個(gè)額外的例外:符合內(nèi)部協(xié)議的元素?cái)?shù)組_ObjectiveCBridgeable
(例如Int
,隱式地橋接到and NSNumber
type,UInt
,和Double
,String
以及其他)可直接分配給元素類型AnyObject
(Array<AnyObject>
)的數(shù)組,方法是在后臺(tái)使用從本機(jī)Swift類型到對(duì)應(yīng)的Cocoa數(shù)據(jù)類型的每個(gè)成員隱式轉(zhuǎn)換。
添加回答
舉報(bào)