Преобразование типов при использовании протокола в 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
, который больше. Чтобы достичь этого, он создает коробку, в которой хранится нечто, соответствующее Test
Msgstr "Ящик имеет известный размер, и ему может потребоваться выделить кучу того, на что он указывает (или, возможно, нет; зависит), но он не будет того же размера, что и оба 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