Protokol bileşimi, Swift'te aynı anda birden fazla protokole uyması gereken bir tür oluşturmayı sağlayan bir mekanizmadır. Bu, Swift'te sınıflar için olmayan çoklu kalıtımın alternatif bir yoludur.
Sorunun Tarihi
Objective-C, çoklu kalıtımı yalnızca protokoller için destekliyordu, ancak sınıflar için değil. Swift, yeni abstractions oluşturmak için protokollere ve bunların kombinasyonuna vurgu yaparak bu geleneği sürdürüyor.
Problem
Programcılar sıklıkla, davranışları birden fazla abstractions tarafından tanımlanan bir tür oluşturma görevini üstlenir. Çoklu kalıtım kaçınılmaz olarak hiyerarşi çatışmalarına yol açar, bu Swift'te protokoller ve protokol bileşimi sayesinde güvenli bir şekilde çözülür.
Çözüm
Swift'te protokolleri '&' operatörü ile birleştirmek mümkündür. Bu, birden fazla protokole aynı anda uyması gereken değişkenler veya fonksiyon parametreleri oluşturmayı sağlar.
Kod örneği:
protocol Drivable { func drive() } protocol Flyable { func fly() } struct FlyingCar: Drivable, Flyable { func drive() { print("Driving") } func fly() { print("Flying") } } func testVehicle(_ vehicle: Drivable & Flyable) { vehicle.drive() vehicle.fly() } testVehicle(FlyingCar())
Anahtar noktalar:
Sadece bir protokolü uygulayan bir nesneyi protokol bileşeni olan bir parametreye geçirebilir miyiz?
Hayır, nesne, bileşimde yer alan tüm protokolleri uygulamak zorundadır; aksi takdirde derleyici hata verir.
Kod örneği:
// struct Car: Drivable {} — testVehicle'a geçirilemez, çünkü fly() uygulanmamış
Protokol bileşimi, sadece değerlere değil türlere de uygulanır mı?
Protokol bileşimi değerlere (değişkenler, fonksiyon parametreleri) uygulanır, ancak bir nesne türü tanımlamada kullanılmaz (örneğin, yeni bir türü herhangi bir „protokol bileşimi” olarak ilan etmek mümkün değildir - yalnızca değişken).
Kod örneği:
var obj: SomeProtocol & AnotherProtocol // geçerli // typealias MyType = SomeClass & AnotherProtocol // hata
& ile sınıfları ve protokolleri birleştirmek mümkün mü?
Evet, ancak bir sınıf türü (sınıf veya onun miras aldığı) sol tarafta yalnızca bir tane olabilir, diğerleri yalnızca protokoller olmalıdır; aksi takdirde derleyici hata verir.
Kod örneği:
class A {} protocol B {} // func f(obj: A & B) {} // geçerli // func f(obj: A & AnotherClass & B) {} // hata! Yalnızca bir sınıf türüne izin verilir
Projede katmanlar arasında veri iletimi için protokol bileşimi kullanan nesneler kullanılıyor, oysa sadece bir protokol yeterliydi:
func present(item: Displayable & Serializable) { ... }
Artıları:
Protokol bileşiminin yalnızca açık durumlarda kullanılması — örneğin, Genel serileştirme için hem Codable hem de Identifiable'ı aynı anda destekleyen nesnelerin işlenmesi:
func save<T: Codable & Identifiable>(_ item: T) { ... }
Artıları: