Sorunun Geçmişi:
Subscript, koleksiyonlar, yapılar ve diğer türler içindeki değerlere köşeli parantezler aracılığıyla erişme mekanizmasıdır. Diğer dillerle (örneğin, Python'daki dizinleme, C++/Java'daki [] operatörü) benzerlik göstermek üzere Swift'e eklenmiştir, böylece koleksiyonlar ve benzeri nesnelerle çalışma daha sezgisel hale gelir.
Problemler:
Tüm türler varsayılan olarak dizine göre erişimi desteklemez. Veri içeren bir yapı veya sınıfımız olduğunda, elemanlara erişim genellikle alışıldık söz dizimi (örneğin myObject[index]) aracılığıyla gerçekleştirilmesi daha mantıklıdır, yöntem aracılığıyla değil.
Çözüm:
Swift, her kullanıcı tanımlı tür için subscripting'i kendinizin uygulamasına izin verir. Bunu hem okuma hem de yazma için yapabilirsiniz. Örnek olarak, kare matrisle çalışmak için subscript'i uygulayan bir yapı:
struct Matrix { let size: Int private var grid: [Int] init(size: Int) { self.size = size self.grid = Array(repeating: 0, count: size * size) } subscript(row: Int, column: Int) -> Int { get { precondition(indexIsValid(row, column), "Index out of range") return grid[(row * size) + column] } set { precondition(indexIsValid(row, column), "Index out of range") grid[(row * size) + column] = newValue } } private func indexIsValid(_ row: Int, _ column: Int) -> Bool { return row >= 0 && row < size && column >= 0 && column < size } } var m = Matrix(size: 3) m[1,2] = 7 print(m[1,2]) // 7
Anahtar özellikler:
Subscript yalnızca koleksiyonlar için mi kullanılabilir?
Hayır, subscript herhangi bir tür için uygulanabilir: yapı, sınıf, enum. İçindeki veri türü bir koleksiyon olmak zorunda değildir, önemli olan subscript aracılığıyla sorgu işleme mantığıdır.
Bir türde farklı imzaya sahip birden fazla subscript oluşturmak mümkün mü?
Evet, farklı parametre imzalarına sahip subscript'leri aşırı yüklemek mümkündür:
struct Example { subscript(index: Int) -> Int { return index } subscript(key: String) -> String { return key.uppercased() } }
Subscript, set olmadan hesaplanmış bir özellik olarak kullanılabilir mi?
Evet, subscript yalnızca okuma (get-only) olabilir, bu durumda yazma girişimi derleme hatasına neden olur.
struct ReadOnly { subscript(index: Int) -> Int { index * index } }
Büyük bir yapıda aralık kontrolü olmadan bir subscript uygulanır, bu da yanlış bir indeksle uygulamanın çökmesine neden olur.
Artılar:
Eksiler:
Matris, indeks aralığı için precondition ile uygulanmıştır. Herhangi bir hata hemen yakalanır, produksiyona ulaşmaz.
Artılar:
Eksiler: