Swift dilinde tip dönüşümü mekanizması, bir değerin bir tipten diğerine dönüştürülmesi ve kontrol edilmesi görevini çalıştırma zamanında çözer. Bunun kökleri, statik tip sistemine ve kalıtasına dayanır: Swift'te aynı anda value-tipleri (struct/enum) ve reference-tipleri (class/protocol) ile çalışmak mümkündür. Sorun, bir nesne veya değerin Any tipi veya bir protokole sahip bir değişkene geldiğinde ortaya çıkar - ve bunun daha spesifik bir tipe dönüştürülüp dönüştürülmeyeceğini (genellikle daha spesifik) riske atmadan bilmek gerekir.
Güvenli tip dönüşümü, tip güvenliğinden, dinamik polimorfizmden yararlanmayı sağlar ve karışık koleksiyonlar veya sınıf hiyerarşileriyle çalışırken hata yapmayı önler.
Swift, üç tip dönüşüm biçimi sağlar:
as — güvenli dönüşüm (upcast), burada derleyici sonuç her zaman önceden biliniras? — yalnızca koşullu (optional) dönüşüm (downcast), dönüşüm başarısız olursa optional döneras! — zorunlu (forced) dönüşüm, dönüşüm mümkün değilse çalışma zamanı hatası (runtime crash) oluştururKod örneği:
class Animal {} class Dog: Animal { func bark() { print("Woof!") } } let animals: [Animal] = [Dog(), Animal()] for animal in animals { if let dog = animal as? Dog { dog.bark() // güvenli cast as? } else { print("Not a dog!") } }
Önemli özellikler:
Bağlantılı olmayan tipler arasında (örneğin, String'den Int'ye) as! operatörünü kullanmak mümkün mü? Bu neyle sonuçlanır?
as! operatörü, tipler uyumsuzsa veya aralarında miras alma veya ortak bir protokol hiyerarşisi yoksa her zaman çalışma zamanı hatasına (runtime crash) yol açar. Temel olarak farklı tipler arasında dönüşüm yapmak kabul edilemez.
Kod örneği:
let value: Any = "abc" let num = value as! Int // çökme: 'String' türündeki değeri 'Int' türüne dönüştürme başaramadı
Hiçbir hiyerarşi ile olmayan bir tipe as? ile dönüşüm yaparsak ne olur?
as? her zaman dönüşüm güvenli değilse nil döner - miras alma veya uygulanabilir protokollerle ilgili olsa bile.
Kod örneği:
let value: Any = 5 if let str = value as? String { print(str) } else { print("Can't cast to String") // Bu dal çalışacak }
Sınıf hiyerarşisinde aşağı dönüşüm (downcasting) için as kullanmak mümkün mü?
Hayır. as operatörü yalnızca upcast için uygundur (örneğin, Dog'dan Animal'a veya uygulanmış bir protokole dönüşüm yaparken). Aşağı dönüşümler için her zaman as? veya as! kullanılır.
Kod örneği:
let animal: Animal = Dog() // let dog = animal as Dog // Derleme zamanı hatası let dog = animal as? Dog // Doğru yol
Projede yanlışlıkla metin ve sayılar içeren [Any] koleksiyonu vardı. Verileri işlemek için geliştirici birçok yerde let value = item as! String yazdı ve bu, dizide bir sayı belirdiğinde çöküşe neden oldu.
Artılar:
Eksiler:
Birleşik türler enum kullanarak yeniden yazdık:
enum Payload { case text(String); case number(Int) } let data: [Payload] = [.text("abc"), .number(1)]
Artılar:
Eksiler: