Ответ 1
Удивительно, что компилятор разрешает переопределение в расширении. Это не компилируется:
class A {
func doThing() {
print("dothing super class")
}
}
class B: A {
}
extension B {
override func doThing() { // error: declarations in extensions cannot override yet
print("dothing sub class")
super.doThing()
}
}
В вашем примере, кажется, что компилятор дает вам пропуск, потому что A происходит от NSObject - предположительно, чтобы позволить этому классу взаимодействовать с Objective-C. Это скомпилирует:
class A : NSObject {
func doThing() {
print("dothing super class")
}
}
class B: A {
}
extension B {
override func doThing() {
print("dothing sub class")
super.doThing()
}
}
Мое предположение заключается в том, что факт, что вы позволили сделать это переопределение вообще, сам по себе может быть ошибкой. docs говорят:
Расширения могут добавлять новые функции к типу, но они не могут переопределить существующие функции.
И переопределение нигде не упоминается как одна из вещей, которые может сделать расширение. Поэтому кажется, что это не должно компилироваться. Однако, возможно, это разрешено специально для совместимости с Objective-C, как я уже говорил. В любом случае, мы изучаем краевой кейс, и вы очень хорошо вызвали его отвращение.
В частности, предыдущий код по-прежнему не приводит к тому, что динамическая отправка становится работоспособной. Поэтому вам нужно объявить doThing
как dynamic
, как было предложено @jtbandes, или поместить его в фактический класс, а не в расширение - если вы хотите, чтобы полиморфизм работал. Таким образом, это работает так, как вы ожидаете:
class A : NSObject {
dynamic func doThing() {
print("dothing super class")
}
}
class B: A {
}
extension B {
override func doThing() {
print("dothing sub class")
super.doThing()
}
}
И так:
class A : NSObject {
func doThing() {
print("dothing super class")
}
}
class B: A {
override func doThing() {
print("dothing sub class")
super.doThing()
}
}
Мое заключение было бы: очень хороший пример; отправьте его Apple в качестве возможной ошибки; и не делай этого. Сделайте свое переопределение в классе, а не в расширении.