Mam tendencję do umieszczania tylko niezbędnych elementów (przechowywanych właściwości, inicjatorów) w definicjach moich klas i przenoszę wszystko inne do ich własnych extension
, podobnie jak w przypadku extension
bloku logicznego, z // MARK:
którym również bym się grupował.
Na przykład w przypadku podklasy UIView chciałbym otrzymać rozszerzenie do rzeczy związanych z układem, jedno do subskrybowania i obsługi zdarzeń i tak dalej. W tych rozszerzeniach nieuchronnie muszę przesłonić niektóre metody UIKit, np layoutSubviews
. Nigdy nie zauważyłem żadnych problemów z tym podejściem - do dzisiaj.
Weźmy na przykład tę hierarchię klas:
public class C: NSObject {
public func method() { print("C") }
}
public class B: C {
}
extension B {
override public func method() { print("B") }
}
public class A: B {
}
extension A {
override public func method() { print("A") }
}
(A() as A).method()
(A() as B).method()
(A() as C).method()
Wynik jest A B C
. To nie ma dla mnie sensu. Czytałem o statycznym wysyłaniu rozszerzeń protokołów, ale to nie jest protokół. Jest to zwykła klasa i oczekuję, że wywołania metod będą dynamicznie wysyłane w czasie wykonywania. Oczywiście wezwanie C
powinno być przynajmniej dynamicznie wysyłane i produkować C
?
Jeśli usunę dziedziczenie z NSObject
i C
utworzę klasę root, kompilator narzeka, mówiąc declarations in extensions cannot override yet
, o czym już czytałem. Ale w jaki sposób posiadanie NSObject
klasy głównej zmienia rzeczy?
Przenoszenie zarówno przesłonięcia do ich deklaracji klasy produkuje A A A
zgodnie z oczekiwaniami, poruszając tylko B
„s produkuje A B B
, poruszając tylko A
” s produkuje C B C
, z których ostatni ma absolutnie żadnego sensu dla mnie: nie nawet jeden statycznie wpisane do A
produkuje A
-Output więcej!
dynamic
Wydaje się, że dodanie słowa kluczowego do definicji lub zastąpienia daje mi pożądane zachowanie `` od tego punktu w hierarchii klas w dół '' ...
Zmieńmy nasz przykład na coś nieco mniej skonstruowanego, co właściwie skłoniło mnie do postawienia tego pytania:
public class B: UIView {
}
extension B {
override public func layoutSubviews() { print("B") }
}
public class A: B {
}
extension A {
override public func layoutSubviews() { print("A") }
}
(A() as A).layoutSubviews()
(A() as B).layoutSubviews()
(A() as UIView).layoutSubviews()
Teraz mamy A B A
. Tutaj nie mogę w żaden sposób nadać dynamiki layoutSubviews UIView.
Przeniesienie obu nadpisań do ich deklaracji klasy daje nam A A A
ponownie, tylko A lub tylko B nadal nas dostaje A B A
. dynamic
znowu rozwiązuje moje problemy.
Teoretycznie mógłbym dodać dynamic
do wszystkiego, override
co kiedykolwiek robię, ale czuję, że robię tu coś innego źle.
Czy naprawdę źle jest używać extension
s do grupowania kodu, tak jak ja?