Я схильний лише вносити необхідні речі (збережені властивості, ініціалізатори) у свої визначення класу та переміщувати все інше у свої власні extension
види, подібні до extension
логічного блоку, з яким я б // MARK:
також групувався.
Наприклад, для підкласу UIView я б закінчив розширення для матеріалів, пов’язаних з компонуванням, підписки та обробки подій тощо. У цих розширеннях мені неминуче доведеться перекрити деякі методи UIKit, наприклад layoutSubviews
. Я ніколи не помічав жодних проблем із таким підходом - до сьогодні.
Візьмемо для прикладу цю ієрархію класів:
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()
Вихід є A B C
. Це для мене мало сенсу. Я читав про розширення протоколів, які розсилаються статично, але це не протокол. Це звичайний клас, і я очікую, що виклики методів будуть динамічно відправлені під час виконання. Очевидно, що дзвінок C
повинен бути принаймні динамічно відправлений та продукований C
?
Якщо я видаляю спадщину NSObject
і роблю C
клас root, компілятор скаржиться на висловлювання declarations in extensions cannot override yet
, про яке я вже читав. Але як існування NSObject
кореневого класу змінює речі?
Переміщення обох змін у своїй декларації класу створює, A A A
як очікувалося, переміщення тільки продукції B
виробляє A B B
, переміщення тільки продукції A
виробляє C B C
, остання з яких для мене абсолютно не має сенсу: навіть та, яка статично набрана для A
отримання A
вихідного виходу більше!
Додавання dynamic
ключового слова до визначення або переосмислення, здається, дає мені бажану поведінку "з цього моменту в ієрархії класів вниз" ...
Давайте змінимо наш приклад на щось трохи менш побудоване, що насправді змусило мене поставити це питання:
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()
Зараз ми отримуємо A B A
. Тут я не можу жодним чином зробити динамічний макет UIView динамічним.
Переміщення обох змін до їх класової декларації отримує нас A A A
знову, лише A або лише B все ще отримують нас A B A
. dynamic
знову вирішує мої проблеми.
Теоретично я міг би доповнити dynamic
все, override
що коли-небудь роблю, але відчуваю, що роблю щось інше не так.
Чи справді неправильно використовувати extension
s для групування коду, як я?