Преобразование типов при использовании протокола в 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 как! [Test]" всегда ошибаются. У меня есть функция, в которую я должен отправить [Test]. Конвертировать A в Test прост в использовании как. Но когда дело доходит до Array, мне нужно просмотреть все данные. Есть ли хороший способ конвертировать [A] в [Test].

2 ответа

Решение

Ответ Code Different является правильным, но также важно понять, почему вы не можете просто интерпретировать данные, не делая что- либо, конвертируя O(n), чтобы пройтись и обернуть каждый элемент в блок.

[A] массив с элементами размером A, Итак, более или менее, A[1] находится в ячейке памяти A[0] + sizeof(A) (это не совсем так, но притворись, что так будет проще).

[Test] должен иметь возможность хранить все, что соответствует протоколу. Это может быть размер Aэто может быть размер B, который больше. Чтобы достичь этого, он создает коробку, в которой хранится нечто, соответствующее TestMsgstr "Ящик имеет известный размер, и ему может потребоваться выделить кучу того, на что он указывает (или, возможно, нет; зависит), но он не будет того же размера, что и оба A а также Bтак что макет [Test] в памяти должен отличаться от макета [A] или же [B],

Сейчас as [Test] может сделать это O (N) ходить за вас и заставить копию прямо сейчас. Или это задержит копирование до тех пор, пока вы в первый раз что-то не измените, но это будет намного сложнее и похоронит событие O(n) (возможно, дорогое, возможно, выделение памяти) внутри as такое чувство, что оно должно быть O(1) и не выделять память. Так что есть причины не делать этого.

Когда-нибудь они могут сделать это в любом случае, чтобы упростить задачу для вызывающего абонента, но это сопряжено с затратами как на производительность, так и на сложность, и поэтому сегодня этого не происходит, и вам нужно составить карту самостоятельно.

Если вы хотите гораздо глубже погрузиться в эту штуку, с более подробной информацией о том, как работает этот блок (и меньше "притвориться, что он проще, чем есть"), см. Понимание производительности Swift от WWDC 2016.

Вы не можете конвертировать массив оптом таким образом. использование map:

let f = e.map { $0 as Test } // f is now a [Test] array
Другие вопросы по тегам