亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

為什么[SomeStruct]無法轉換為[Any]?

為什么[SomeStruct]無法轉換為[Any]?

考慮以下:struct SomeStruct {}var foo: Any!let bar: SomeStruct = SomeStruct()foo = bar // Compiles as expectedvar fooArray: [Any] = []let barArray: [SomeStruct] = []fooArray = barArray // Does not compile; Cannot assign value of type '[SomeStruct]' to type '[Any]'我一直在尋找背后的邏輯,但是沒有運氣。值得一提的是,如果將結構更改為類,則效果很好。總是可以添加一種解決方法,并將fooArray的每個對象映射為強制類型為Any,但這不是這里的問題。我正在尋找一種解釋,為什么會這樣。
查看完整描述

3 回答

?
收到一只叮咚

TA貢獻1821條經驗 獲得超5個贊

Swift 3更新

從Swift 3(特別是Xcode 8 beta 6附帶的內部版本)開始,集合類型現在可以在幕后執行,從值類型元素集合到抽象類型元素集合的轉換。


這意味著現在將編譯以下內容:


protocol SomeProtocol {}

struct Foo : SomeProtocol {}


let arrayOfFoo : [Foo] = []


let arrayOfSomeProtocol : [SomeProtocol] = arrayOfFoo

let 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 here

fooArray = barArray.map {$0 as Any} 

在這里避免隱式“幕后”轉換的一個很好的理由是由于Swift將抽象類型存儲在內存中的方式。使用“現有容器”是為了將任意大小的值存儲在固定的內存塊中–這意味著可能會為無法容納在該容器中的值進行昂貴的堆分配(僅允許引用要存儲在其中的內存)該容器)。


因此,由于數組現在在內存中的存儲方式發生了重大變化,因此禁止隱式轉換是很合理的。這使程序員可以清楚地知道,他們必須轉換數組的每個元素-導致內存結構發生這種更改(可能非常昂貴)。


有關Swift如何與抽象類型一起工作的更多技術細節,請參閱關于主題的WWDC精彩演講。有關Swift中類型差異的更多信息,請參見有關該主題的精彩博客文章。


最后,請確保在下面看到@dfri關于數組可以隱式轉換元素類型的其他情況的注釋 –即,當元素可橋接到Objective-C時,它們可以由數組隱式完成。


查看完整回答
反對 回復 2019-09-27
?
手掌心

TA貢獻1942條經驗 獲得超3個贊

Swift無法自動在包含值類型和引用類型的數組之間進行轉換。只需將數組映射到所需的類型即可:

fooArray = barArray.map({$ 0})//是否編譯


查看完整回答
反對 回復 2019-09-27
?
MM們

TA貢獻1886條經驗 獲得超2個贊

由于您提到了從子類類型(和實例)的數組到超類類型的數組的轉換的例外,因此我可能要添加一個額外的例外:符合內部協議的元素數組_ObjectiveCBridgeable(例如Int,隱式地橋接到and NSNumbertype,UInt,和Double,String以及其他)可直接分配給元素類型AnyObjectArray<AnyObject>)的數組,方法是在后臺使用從本機Swift類型到對應的Cocoa數據類型的每個成員隱式轉換。

查看完整回答
反對 回復 2019-09-27
  • 3 回答
  • 0 關注
  • 805 瀏覽

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號