Я стараюсь помещать только необходимые (сохраненные свойства, инициализаторы) в определения моих классов и перемещать все остальное в свои собственные 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корневой класс, компилятор жалуется, говоря declarations in extensions cannot override yet, о чем я уже читал. Но как наличие NSObjectкорневого класса меняет ситуацию?
Перемещение обоих переопределений в их объявление класса дает A A Aожидаемые результаты, перемещение только Bпроизводит A B B, перемещение только Aпроизводит C B C, последнее из которых не имеет для меня абсолютно никакого смысла: даже тот, который статически типизирован для Aсоздания A-output, больше не имеет!
Добавление 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снова, только либо только B по - прежнему получает нас A B A. dynamicснова решает мои проблемы.
Теоретически я мог бы добавить dynamicко всему, overrideчто делаю, но чувствую, что делаю здесь что-то еще не так.
Неужели неправильно использовать extensions для группировки кода, как я?