Protocol extensions, Swift'te protocol-oriented programming ideolojisini desteklemek için tanıtılmıştır: programcı, varsayılan metod implementasyonlarını doğrudan protokol seviyesinde ekleyebilir, böylece bir temel sınıf veya global fonksiyonlar kullanmaya gerek kalmaz. Bu, kod tekrarını azaltır ve türlerin davranışını esnek bir şekilde uyarlamayı sağlar.
Sorun, varsayılan implementasyonun kendi (override) gereksinimini maskelemesi veya sorumluluk çizgisinin bulanıklaşması durumunda ortaya çıkar — özellikle bir tür birden fazla protokolü uyguladığında ve bunlar arasında çakışmalar olduğunda. Ayrıca, eğer bir metod türde kendisi uygulanıyorsa, o metod her zaman extension'dan gelen implementasyonu geçersiz kılacaktır.
Çözüm — protocol extensions'ı yalnızca evrensel davranışlar için kullanmak, belirli durumlarda ise açıkça metodun içerikte tanımlanmasıdır. Aynı protokol için iki extension'da aynı metodun aşırı yüklenmesinden kaçınmak tercih edilmelidir.
Kod örneği:
protocol Flyer { func fly() } extension Flyer { func fly() { print("Varsayılan uçuş") } } struct Bird: Flyer {} let sparrow = Bird() sparrow.fly() // Çıktı: Varsayılan uçuş
Anahtar özellikler:
Protokole bir stored property eklemek mümkün mü?
Hayır, yalnızca hesaplanan özellikler ve metodlar protocol extensions'a eklenebilir. Stored properties yasaklanmıştır.
Protokol ve türde aynı isimde farklı implementasyonlar varsa ne olur? Hangi biri çağrılır?
Direkt tür çağrıldığında türün implementasyonu, eğer protokol referansı üzerinden bir örneğe ulaşılırsa — protocol extension'ın implementasyonu çağrılır.
protocol Greeter { func greet() } extension Greeter { func greet() { print("Extension'dan merhaba") } } struct Person: Greeter { func greet() { print("Türden merhaba") } } let person = Person() person.greet() // Türden merhaba let greeter: Greeter = person greeter.greet() // Extension'dan merhaba
Protocol extension'da where kısıtlamaları kullanılabilir mi?
Evet. Bu, protokolü yalnızca belirli türler için genişletmenin güçlü bir yoludur.
extension Collection where Element: Equatable { func allEqual() -> Bool { guard let first = self.first else { return true } return allSatisfy { $0 == first } } }
** Olumsuz durum
Ekip, her hizmetin kendi özel formatını eklemek isteyeceğini öngörmeden logging hatalarını protocol extension aracılığıyla gerçekleştirmeye karar verdi. Sonuçta, farklı hizmetler protokol referansları üzerinden fonksiyonu çağırdığı için, davranış mantığı beklenenden farklılık gösterdi.
Artıları:
Eksileri:
** Olumlu durum
Protokol, her zaman evrensel olan durumlar için yalnızca genişletilmektedir. Özel durumlar için ise, türde metodun açık bir şekilde uygulanması, çatışma yerleri için code review yapılır.
Artıları:
Eksileri: