在Swift中使用协议时键入转换

时间:2016-07-15 03:05:05

标签: swift

protocol Test{

    var t: Int {set get}

}

struct A: Test{

    var t: Int

}

struct B: Test{

    var t: Int
    var s: String

}

let a = A(t: 1)
let b = B(t: 2, s: "1")

let c = a as Test

let d: [Test] = [a, b]

let e: [A] = [a, a]

let f = e as [Test]

let g = e as! [Test]

"让f = e作为[Test],让g = e为! [测试]"总是出错。我有一个功能,我必须发送[测试]。将A转换为Test易于使用。但是当涉及到Array时,我必须遍历所有数据。有没有什么好方法可以将[A]转换为[测试]。

2 个答案:

答案 0 :(得分:6)

代码不同的答案是正确的,但理解为什么在没有 进行O(n)转换的情况下重新解释数据也很重要然后走路并将每个元素包装在一个盒子里。

[A]是一个数组大小为A的数组。因此,或多或少,A[1]位于记忆位置A[0] + sizeof(A)(这不是完全正确的,但假装它是;它会使事情变得更简单。)

[Test]必须能够容纳符合协议的任何。它可能是A的大小,可能是B的大小,它更大。为了实现这一点,它创建了一个框,其中包含符合Test"的内容。该框具有已知大小,它可能必须堆积分配它指向的东西(或者可能不是;依赖),但它不会与AB[Test],因此内存中[A]的布局必须与[B]as [Test]的布局不同。

现在as可以为你做O(n),然后强行复制。或者它会延迟复制,直到你第一次修改某些东西,但它会复杂得多,它会在handleLogin = () => { LoginManager.logInWithReadPermissions(['public_profile']).then( function(result) { if (result.isCancelled) { alert('Login cancelled'); } else { alert('Login success with permissions: ' + result.grantedPermissions.toString()); } }, function(error) { alert('Login fail with error: ' + error); } ) } 内埋一​​个O(n)(可能是昂贵的,可能是内存分配)的事件。是O(1)并且不分配内存。所以有理由不这样做。

有一天,他们可能会这样做,以便让来电者更简单,但是在性能和​​复杂性方面都有成本,所以今天它没有做到,你需要自己做地图

如果你想更深入地了解这些内容,有关这个框如何工作的更多细节(并且更少"假装它比它更简单"),请参阅Understanding Swift Performance来自WWDC 2016。

答案 1 :(得分:3)

您不能像这样批量转换阵列。使用map

let f = e.map { $0 as Test } // f is now a [Test] array