Ответ 1
Как отмечают другие, Swift еще не позволяет переопределить метод, объявленный в расширении класса. Тем не менее, я не уверен, что вы когда-либо получите нужное поведение, даже если/когда Swift когда-нибудь позволит вам переопределить эти методы.
Рассмотрим, как Swift имеет дело с протоколами и расширениями протокола. Учитывая протокол для печати некоторых имен метасинтетических переменных:
protocol Metasyntactic {
func foo() -> String
func bar() -> String
}
Расширение для реализации по умолчанию:
extension Metasyntactic {
func foo() -> String {
return "foo"
}
func bar() -> String {
return "bar"
}
}
И класс, соответствующий протоколу:
class FooBar : Metasyntactic {
func foo() -> String {
return "FOO"
}
func bar() -> String {
return "BAR"
}
}
Swift будет использовать динамическую диспетчеризацию для вызова соответствующих реализаций foo()
и bar()
на основе каждого типа времени выполнения переменной, а не типа, указанного компилятором:
let a = FooBar()
a.foo() // Prints "FOO"
a.bar() // Prints "BAR"
let b: Metasyntactic = FooBar()
b.foo() // Prints "FOO"
b.bar() // Prints "BAR"
Если, однако, мы расширяем протокол для добавления нового метода:
extension Metasyntactic {
func baz() -> String {
return "baz"
}
}
И если мы переопределим наш новый метод в классе, который соответствует протоколу:
class FooBarBaz : Metasyntactic {
func foo() -> String {
return "FOO"
}
func bar() -> String {
return "BAR"
}
func baz() -> String {
return "BAZ"
}
}
Теперь Swift будет использовать статическую диспетчеризацию для вызова соответствующей реализации baz()
на основе типа, указанного компилятором:
let a = FooBarBaz()
a.baz() // Prints "BAZ"
let b: Metasyntactic = FooBarBaz()
b.baz() // Prints "baz"
Alexandros Salazar имеет фантастическое сообщение в блоге, подробно объясняющее это поведение, но достаточно сказать, что Swift использует только динамическую отправку для методов, объявленных в исходный протокол, а не для методов, объявленных в расширениях протокола. Я предполагаю, что то же самое относится и к расширениям классов.