A WWDC 2015 session video, Protokol Yönelimli Programlama fikrini açıklar ve gelecekteki uygulamalarda bu tekniği benimsemek istiyorum. Bu yeni yaklaşımı anlamak için son birkaç günlüğüne Swift 2.0 ile oynuyorum ve bunu Delegate Pattern ile çalışmaya çalışmam için takıldım.Protokol Yönlendirmeli Programlama ve Temsilci Deseni
Projemin ilginç kısmının temel yapısını tanımlayan iki protokoller var (örnek kod saçma ama sorun açıklanır):
1) erişilebilir bazı bilgiler yapar bir heyet protokolü, benzer
protocol ValueProvider {
var value: Int { get }
}
2) Abo bilgilerle bir şey yapar varlığın bir arayüz protokolü: UITableViewController en dataSource protokolüne (A "Protokol-İlk" yaklaşımının fikri devreye girer burada) ettik: Veri işlemcinin gerçek uygulama ile ilgili olarak
protocol DataProcessor {
var provider: ValueProvider { get }
func process() -> Int
}
, şimdi çeteleler, yapılar ve sınıflar arasında seçim yapabilirsiniz. Bilgiyi nasıl işlemek istediğimin birkaç farklı soyutlama seviyesi vardır, bu nedenle sınıflar en iyi şekilde uygun görünmektedir (ancak gelecekteki kullanım durumlarında değişebileceğinden, bunu nihai bir karar vermek istemiyorum). Ben birkaç olaya özgü işlemcileri oluşturabileceği üst (yapılar ve çeteleler mümkün olmayan) üzerinde, bir taban işlemci sınıfını tanımlayabilirsiniz:
class BaseDataProcessor: DataProcessor {
let provider: ValueProvider
init(provider: ValueProvider) {
self.provider = provider
}
func process() -> Int {
return provider.value + 100
}
}
class SpecificDataProcessor: BaseDataProcessor {
override func process() -> Int {
return super.process() + 200
}
}
Yukarı her şeyin bir cazibe gibi çalışır gösteriniz. Bununla birlikte, gerçekte, belirli veri işlemcileri işlenen değerlere sıkı sıkıya bağlıdırlar (bu, değil temel işlemcinin aksine), ValueProvider'u doğrudan alt sınıfa entegre etmek istiyorum. Karşılaştırma için: genellikle, UITableViewControllers kendi dataSource ve temsilcisidir).
Önce bir varsayılan uygulama ile protokol uzantısı ekleyerek düşündüm: Ben değeri bağlı yapmak istemiyoruz BaseDataProcessor sınıfı olmasaydı
extension DataProcessor where Self: ValueProvider {
var provider: ValueProvider { return self }
}
Bu muhtemelen çalışacak. Ancak, BaseDataProcessor ve'dan gelen alt sınıflar ValueProvider'ı benimsemekte, bu uygulamayı dahili olarak geçersiz kılmaktadır, bu bir seçenek değildir.
denemelere devam etti ve bu ile sona erdi: derler ve ilk bakıştaclass BaseDataProcessor: DataProcessor {
// Yes, that's ugly, but I need this 'var' construct so I can override it later
private var _provider: ValueProvider!
var provider: ValueProvider { return _provider }
func process() -> Int {
return provider.value + 10
}
}
class SpecificDataProcessor: BaseDataProcessor, ValueProvider {
let value = 1234
override var provider: ValueProvider { return self }
override func process() -> Int {
return super.process() + 100
}
}
istediğimi yapmama gibi görünmektedir.
weak var p: SpecificDataProcessor!
autoreleasepool {
p = SpecificDataProcessor()
p.process()
}
p // <-- not nil, hence reference cycle!
Başka bir seçenek protokol tanımlarına sınıf kısıtlamaları eklemek olabilir: bir Swift oyun alanında görülebilir bir referans döngüsü üretir Ancak, bu bir çözüm değildir. Ancak, bu benim anladığım kadarıyla POP yaklaşımını kıracaktı.
Sonuç olarak, sorumun aşağıya doğru kaydığını düşünüyorum: Protokol Yönlendirmeli Programlama ve Delege Kalıbı, protokol tasarımı sırasında kendinizi sınıf kısıtlamalarıyla sınırlamadan birlikte nasıl çalışır? Oyun alanlarında autoreleasepool kullanılarak dayanıklı referans döngüsü için uygun değildir bu