Swift'te subscripts, diziler ve sözlükler gibi indeksler aracılığıyla bir koleksiyon, konteyner veya kullanıcı tanımlı tiplere erişim sağlamak için kullanışlı bir sözdizimi sunar. Kendi sınıflarınızda, yapılarınızda ve enum'larınızda tanımlanıp yeniden tanımlanabilir.
Subscripts, Swift'te nesnelere indekslenmiş erişimi birleştirme yolu olarak ortaya çıktı, önce koleksiyonlarla başladı, ardından herhangi bir kullanıcı tanımlı tipe yayıldı. Ana amaç, ifade edilebilirliği ve okunabilirliği artırmak, veri erişim yöntemlerini dizilerle çalışıyormuş gibi "doğal" bir sözdizimine dönüştürmektir.
Diğer dillerde (örneğin, Java) bir yapının elemanına erişim, kodu hacimli hale getiren get/set yöntemleri aracılığıyla gerçekleştirilir. Daha iyi okunabilirlik ve verilere erişimin kolaylaştırılması arayışı, subscripts’i doğurdu. Swift'te güvenli erişim, getter ve setter, olası hatalar ve optional dönen değerler üzerinde özel bir dikkat gereklidir.
Subscript, herhangi bir sınıfta, yapıda veya enum'da subscript anahtar kelimesiyle tanımlanabilir. Ayrıca, parametreler ve dönen tipler bakımından birden fazla overload desteklenir.
Örnek bir kullanıcı subscript'i:
struct Matrix { let rows: Int, columns: Int private var grid: [Double] init(rows: Int, columns: Int) { self.rows = rows self.columns = columns grid = Array(repeating: 0.0, count: rows * columns) } subscript(row: Int, column: Int) -> Double { get { precondition(row >= 0 && row < rows) precondition(column >= 0 && column < columns) return grid[(row * columns) + column] } set { precondition(row >= 0 && row < rows) precondition(column >= 0 && column < columns) grid[(row * columns) + column] = newValue } } } var matrix = Matrix(rows: 2, columns: 2) matrix[1, 1] = 3.14 print(matrix[1, 1]) // 3.14
Ana özellikler:
Yalnızca getter ile subscript ilan edilebilir mi, setter olmadan?
Evet. Eğer subscript yalnızca okuma için gerekiyorsa, sadece get uygulamak yeterlidir.
struct ReadOnlyArray { private let items = [1, 2, 3] subscript(index: Int) -> Int { get { return items[index] } } }
Bir tip içerisinde farklı imzalarla birden fazla subscript ilan etmek mümkün müdür?
Evet, subscript parametre sayısı ve tipine göre overload edilebilir.
struct Collection { subscript(index: Int) -> String { ... } subscript(key: String) -> Int? { ... } }
Bir subscript protokolde ilan edilebilir mi ve bir yapı/sınıf içinde uygulanabilir mi?
Evet, protokoller subscript'in uygulanmasını talep edebilir ve spesifik tiplerin bunları uygulaması zorunludur.
protocol MySubscriptable { subscript(index: Int) -> String { get set } } struct SubData: MySubscriptable { private var items = ["a", "b"] subscript(index: Int) -> String { get { return items[index] } set { items[index] = newValue } } }
Geliştirici sınır kontrolü olmadan subscript'i uyguladı. Bu durumda, var olmayan bir indekse erişimde uygulama runtime hatası ile çöktü.
Artılar: Kod daha derli toplu oldu.
Eksiler: Uygulama ani hatalar nedeniyle başarısız oldu.
Sınır kontrolleri ve optional geri dönüşü veya hata fırlatma imkanı ile subscript'in uygulanması.
Artılar: Kod kullanıcı için daha güvenli hale geldi, hatalar işlenebilir hale geldi.
Eksiler: Hata işleme için ek bir mantık eklenmesi ve geçersiz indeksler için bir davranış planlanması gerekti.