Я схильний лише вносити необхідні речі (збережені властивості, ініціалізатори) у свої визначення класу та переміщувати все інше у свої власні 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що коли-небудь роблю, але відчуваю, що роблю щось інше не так.
Чи справді неправильно використовувати extensions для групування коду, як я?