2017-10-14 99 views
0

我有2 structs只有通過協議相關。我試圖在兩種類型之間進行轉換,因爲它們共享一個協議,但是我得到一個運行時錯誤。僅使用協議在類型之間進行轉換?

這就是我想要做的事:

protocol A { 
    var id: String { get } 
    var name: String { get } 
    var isActive: Bool { get set } 
} 

struct Entity: A { 
    let id: String 
    var name: String 
    var isActive: Bool 

    func someFun() { 
     print("\(name), active: \(isActive)") 
    } 
} 

struct ViewModel: A { 
    let id: String 
    var name: String 
    var isActive: Bool 
} 

let vm = ViewModel(id: "abc", name: "John Doe", isActive: true) 
let pt = vm as A 
let et = pt as! Entity 
print(et.someFun()) //crash 

我得到的錯誤是:

Could not cast value of type '__lldb_expr_87.ViewModel' (0x111835638) to '__lldb_expr_87.Entity' (0x111835550). 

這是一個真正的無賴,因爲如果我有幾百萬的記錄,我不我想要循環每一個手動轉換一個。我希望能暗中神奇投這樣的:

let entity = vm as A as Entity 
let entities = vms as [A] as [Entity] 

任何性能敏感的方式來傳遞邊界之間的對象,而不通過每一個循環?

+0

你不能那樣做,因爲協議只保證兩種類型都實現了協議要求。它並不能保證兩種類型都是可以互換的。順便提一下,Swift提供了'map'之類的函數來避免循環(儘管框架使用循環)。 – vadian

回答

0

正如vadian在他的評論中所述,您不能像這樣類型化。要執行你正在嘗試通過類型轉換做的,你需要做這樣的事情:

let entity = Entity(id: vm.id, name: vm.name, isActive: vm.isActive) 

let entities = vms.map { 
    return Entity(id: $0.id, name: $0.name, isActive: $0.isActive 
} 

你之所以是崩潰是因爲類型轉換不會更改的對象實際上具有的屬性和方法,只有他們訪問的方法和屬性。如果您執行以下,你會失去你的someFun訪問()方法:

let entityAsA = Entity(id: "id", name: "name", isActive: true) as A 

然而,以下將編譯和運行沒有崩潰:

(entityAsA as! Entity).someFun() 

所以,當你試圖從投ViewModel to A to Entity,它不會改變值在內存中創建的方式(不能訪問稱爲someFun()的函數),並且每次都會崩潰。

相關問題