Hangi nedenlerle Swift'teki her delege için ayrı bir sınıf uzantısı kullanırsınız?


13

Bir Ray Wenderlich öğretici ile çalışıyordu ve yazar onları sınıfta yani ele alınması yerine delege geri çağırmaları tutmak için sınıf uzantıları kullandığını fark ettim:

sınıf uzantısı içindeki geri çağrılara temsilci seçme:

extension LogsViewController : UIPopoverPresentationControllerDelegate {
    func adaptivePresentationStyleForPresentationController(controller: UIPresentationController, traitCollection: UITraitCollection) -> UIModalPresentationStyle {
        ...
    }
}

sınıf içinde yer almasının aksine:

sınıf içindeki geri çağrıları delege edin:

class LogsViewController : UITableViewController, UIPopoverPresentationControllerDelegate {
    func adaptivePresentationStyleForPresentationController(controller: UIPresentationController, traitCollection: UITraitCollection) -> UIModalPresentationStyle {
        ...
    }
}

Bunu aynı zamanda garip ve ilginç buldum. Sadece "LogsViewControllerExtension.swift" adlı LogsViewController sınıfındaki uzantılara adanmış bir dosyaya sahiptir ve her delege protokolü için farklı bir uzantıya sahiptir: UITableViewDataSource, UISplitViewDelegate, vb.

her biri kendi dosyasındaki geri çağrıları temsil eden birden çok sınıf uzantısı:

extension LogsViewController: UISplitViewControllerDelegate {
    ... callbacks
}

extension LogsViewController : UIPopoverPresentationControllerDelegate {
    ... callbacks
}

Neden?

Bunu yapmanın ne gibi avantajları var? Bunu ayırmanın nereden daha okunaklı olabileceğini görebiliyorum ama aynı zamanda dolaylı bir seviyedir. Bunu destekleyen veya buna karşı çıkan OO ilkeleri var mı?


1
Temel olarak OO ilkeleri tarafından desteklenen ancak yine de aşırı mühendislikten suçlu olan birçok yapı yazabilirsiniz.
Robert Harvey

1
@RobertHarvey true, ancak burada gösterdiğim örnek kodun bir tür mühendislik olduğunu mu ima ediyorsunuz? Yetkilendirme, iOS geliştirmede yaygın bir modeldir. Ayrıca, sınıf uzantıları kullanıp kullanmadığınız, içindeki kodu değiştirmez, bu nedenle yeniden (/ over)
-engineering

1
Bir grup uzantıyı aynı dosyaya atma şeklini görüyorum ve bunun nereden geldiğini bilmiyorum. Bazı insanlar zaten onu kötüye kullanıyor ve sadece her bir kod parçasını aynı dosyadaki bir uzantıya keyfi olarak atıyor gibi görünüyor. Eminim bunu zaman zaman yapmak için iyi bir neden vardır, ancak bazı programcıların bunu nedenini anlamadan yaptıklarını düşünüyorum. MARK kullanımı konusunda bunun bir avantajını aramaya devam ediyorum: - ve uzantıların neden bu şekilde kullanılması gerektiğine dair kesin bir kaynak bulmak isterim.
David Lari

Yanıtlar:


15

Neden bir miktar dolaylılık eklediğini söylediğini bilmiyorum. Belki de bununla geleneksel anlamdan farklı bir şey kastediyorsunuz, çünkü bunu yaparak fazladan dolaylı bir yol yoktur. Ama neden?

Yapıyorum çünkü daha modüler. Arabirim tarafından gerekli olan tüm kod tek bir yerde gruplanır (gerçek özellikler hariç). Daha sonra bu protokolü uygulamak için ayrı bir sınıf yapmayı seçersem (ve böylece gerçek bir dolaylılık düzeyi tanıtmak), tüm ihtiyacım olan do, uzantıyı kendi sınıfına dönüştürmek (gerekli özellikleri bir init işlevi aracılığıyla iletmek) ve nesneyi örneklemek için ViewController üzerinde bir özellik oluşturmaktır.

Ayrıca, yalnızca bu protokolün işlevleri tarafından kullanılan herhangi bir özel işlevi uzantıya koydum. Uzantı için tamamen ayrı bir dosya oluşturacak kadar ileri gitmedim, ancak bu özel işlevlerin sadece bu protokol için olduğunu açıkça ortaya koyuyor.

Her halükarda, insanlar genellikle yağ görüntüleme denetleyicilerinden şikayet ederler ve bir görünüm denetleyicisini bu şekilde kırmak, görünüm denetleyicisini daha ince yapmasa bile, daha iyi organize edilmesine yardımcı olur.


Ne demek istediğini modülerlikle görüyorum. Neler olduğunu anladıktan sonra, endişeleri ayırmanın temiz bir yolu gibi görünüyordu. Sanırım dolaylılık seviyesi yeni bir göz grubu için (ve Obj-c yolundan gelen önyargılıyım). Ben taban sınıfta başka bir yerde tanımlanmış kod başvurulan alt sınıflama aynı dolaylılık hissediyorum ve onu bulmak biraz daha zor. Örgütsel olarak (biraz dolaylı maliyetle) fayda eklediğini kabul ediyorum
morbidhawk

Bu daha önce Obj-C sınıf kategorileri ile yapılmış sanırım. Ben hiç bu kadar hayranı değildi ama bence ayrı bir dosya gerekli. Swift'ten beri uzantıyı aynı dosyada tutabilirsin, onları böyle
ayırmaya

2

Daniel'in dolaylı anlatımla ilgili söylediği gibi, bunun bir seviyesi yoktur.
Ona katılıyorum ve yakın zamanda tanıdığım Protokol Uzantılarının ekstra güçlü bir özelliğini eklemek istiyorum.

didCopyTextÖrneğin bir protokolünüz olduğunu varsayalım. Bunu şu şekilde uygulayacaksınız:

protocol didCopyText {
  var charachtersCount: Int {get}
  func addToClipboardWith(text: String)
}

Swift'te, Protokol bildiriminde özellikler ve yöntemler uygulanmaz, her sınıftaki didCopyTextuygulamayı, aynı uygulamaya sahip bu protokole uyan artan sayıda sınıfla yazmak istersiniz, sadece dağınık bir sonuçla sonuçlanır. tekrarlanan kod. Protokol Uzantıları burada işe yarar.

protocol didCopyText {
var charachtersCount: Int {
    get {
     // implementation
    }
}
func addToClipboardWith(text: String) {
      // implementation
 }
}

Protokolün özellikleri ve yöntemlerinin uygulanması ile. Şimdi, herhangi bir sınıf bu protokole uygun, aynı uygulamayı kullanacaktır.


bunu paylaştığın için teşekkürler. Bu soruyu sorduğumda, OO mirasının bazı dezavantajları hakkında farkında değildim ve burada açıkladığınız şey, zorlamak yerine o arayüze uyan tüm uygulayıcı sınıflar tarafından aynı işlevleri yeniden kullanmanın harika bir yoludur. her şeyi bir nesneden miras alır. Ayrıca, Arabirim Ayrımı ilkesini uygularsanız, uygulayıcı sınıfların hiçbir zaman ihtiyaç duymadıkları arabirimden özelliklere / yöntemlere sahip olmamasını sağlamak için gereken protokolleri ayırabilirsiniz.
morbidhawk

1

Sınıfınızın üç protokolü desteklediğini ve bu nedenle üç işlev kümesi eklemeniz gerektiğini varsayalım. Bu işlevlerin tek amacı bir protokolü desteklemektir, bu nedenle bazı belgelere ihtiyacınız vardır.

Bununla birlikte, her protokol için bir uzantı eklerseniz ve her uzantıda bu protokol için gereken işlevleri tam olarak uygularsanız, kodunuzu daha okunabilir hale getirir.

Bu uzantılar gerçekten büyük olmadıkça büyük olasılıkla bunları ayrı dosyalara koymam.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.