Pracowałem przez samouczek Raya Wenderlicha i zauważyłem, że autor używa rozszerzeń klas do przechowywania wywołań zwrotnych delegatów zamiast obsługi ich w samej klasie, tj .:
delegować wywołania zwrotne wewnątrz rozszerzenia klasy:
extension LogsViewController : UIPopoverPresentationControllerDelegate {
func adaptivePresentationStyleForPresentationController(controller: UIPresentationController, traitCollection: UITraitCollection) -> UIModalPresentationStyle {
...
}
}
w przeciwieństwie do umieszczenia go w klasie:
delegować wywołania zwrotne w klasie:
class LogsViewController : UITableViewController, UIPopoverPresentationControllerDelegate {
func adaptivePresentationStyleForPresentationController(controller: UIPresentationController, traitCollection: UITraitCollection) -> UIModalPresentationStyle {
...
}
}
Uznałem to za dziwne i jednocześnie interesujące. Ma plik dedykowany tylko rozszerzeniom klasy LogsViewController o nazwie „LogsViewControllerExtension.swift” i ma inne rozszerzenie dla każdego protokołu delegowanego: UITableViewDataSource, UISplitViewDelegate itp. Tj .:
wiele rozszerzeń klas, każde z wywołaniami zwrotnymi delegatów wewnątrz własnego pliku:
extension LogsViewController: UISplitViewControllerDelegate {
... callbacks
}
extension LogsViewController : UIPopoverPresentationControllerDelegate {
... callbacks
}
Dlaczego?
Jakie są zalety tego działania? Widzę, gdzie może być trochę bardziej czytelne, aby to oddzielić, ale jednocześnie jest to poziom pośredni. Czy istnieją zasady OO, które wspierają lub nie robią tego?
źródło
Odpowiedzi:
Nie wiem, dlaczego powiedziałeś, że dodaje poziom pośredni. Może masz przez to na myśli coś innego niż tradycyjne znaczenie, ponieważ dzięki temu nie powstaje żadna dodatkowa pośrednictwo. Ale dlaczego to robisz?
Robię to, ponieważ jest bardziej modułowy. Cały kod wymagany przez interfejs jest pogrupowany w jednym miejscu (z wyjątkiem faktycznych właściwości.) Jeśli później zdecyduję się stworzyć osobną klasę do wdrożenia tego protokołu (a tym samym wprowadzić rzeczywisty poziom pośredni), wszystko, czego potrzebuję zrobić to zmienić rozszerzenie na własną klasę (przekazując potrzebne właściwości za pomocą funkcji init) i utworzyć właściwość w ViewController, aby utworzyć instancję obiektu.
W rozszerzeniu umieściłem również funkcje prywatne, które są używane tylko przez funkcje tego protokołu. Nie posunąłem się tak daleko, aby utworzyć całkowicie oddzielny plik dla rozszerzenia, ale czyni to jasne, że te prywatne funkcje są tylko dla tego protokołu.
W każdym razie ludzie często narzekają na kontrolery fat view, a rozbicie kontrolera view w ten sposób pomaga lepiej go zorganizować, nawet jeśli tak naprawdę nie cieńszy kontrolera view.
źródło
Jak powiedział Daniel w odniesieniu do pośrednictwa, nie ma jego poziomu.
Zgadzam się z nim i chciałbym dodać dodatkową potężną funkcję rozszerzeń protokołu, którą znałem ostatnio.
Powiedz, że masz
didCopyText
na przykład protokół . Zaimplementujesz to jako:W Swift właściwości i metody nie są zaimplementowane w deklaracji protokołu, chciałbyś napisać implementację w każdej klasie
didCopyText
zgodnej z, przy przyrostowej liczbie klas zgodnych z tym protokołem z tą samą implementacją, skończyłoby się to tylko bałaganem powtarzający się kod. Przydają się rozszerzenia protokołu.Dzięki implementacji właściwości i metod protokołu. Teraz każda klasa jest zgodna z tym protokołem i będzie korzystać z tej samej implementacji.
źródło
Powiedzmy, że twoja klasa obsługuje trzy protokoły i dlatego musisz dodać trzy zestawy funkcji. Jedynym celem tych funkcji jest obsługa protokołu, dlatego potrzebujesz trochę dokumentacji.
Jeśli jednak dodasz rozszerzenie dla każdego protokołu, a dla każdego rozszerzenia zaimplementujesz dokładnie funkcje potrzebne dla tego jednego protokołu, dzięki czemu Twój kod będzie znacznie bardziej czytelny.
Najprawdopodobniej nie umieściłbym ich w osobnych plikach, chyba że te rozszerzenia są naprawdę duże.
źródło