Я стараюсь только поместить необходимые вещи (хранимые свойства, инициализаторы) в свои определения классов и переместить все остальное в свой собственный 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 layoutSubviews динамическим любым способом.
Перемещение обоих переопределений в их объявление класса снова возвращает нас A A A
, только A или только B все еще получает нас A B A
. dynamic
снова решает мои проблемы.
В теории я мог бы добавить dynamic
ко всем override
, которые я когда-либо делал, но чувствую, что я делаю что-то еще не так.
Действительно ли неправильно использовать extension
для группировки кода, как я?