Какая механика лежит в основе методов расширения, переопределяемых атрибутом '@objc'? - PullRequest
0 голосов
/ 24 февраля 2019

Вроде вопрос кретина.Мне неясно, что именно делает этот код работающим:

class Shape { }

extension Shape {
    @objc func redraw() {
        print("from ext")
    }
}

class Circle: Shape { }

class Line: Shape {
    override func redraw() { // Compiler error: Declarations from extensions cannot be overridden yet
        print("from subclass")
    }
}

let line = Line()
let shape:Shape = line
let circle = Circle()

line.redraw() //from subclass
circle.redraw() //from ext
shape.redraw() //from subclass

Если я опущу ключевое слово @objc в расширении, код не будет компилироваться - это ожидаемое поведение, так как методы в расширении используют статический метод dispatch -> не может быть отменено.Но почему добавление @objc заставляет его работать?Согласно документации и большинству статей, все, что делает @objc, это делает вещи видимыми во время выполнения Objective-c.Для изменения типа отправки метода существует специальное ключевое слово - dynamic.Но, похоже, в этом нет необходимости!

Помогите разобраться, почему добавление @objc (и пропуск dynamic) делает такие вещи возможными.

1 Ответ

0 голосов
/ 24 февраля 2019

Расширения ,

, как уже сказано в названии, должны расширять / добавлять / включать методы в существующую реализацию, делая их одной из самых красивых вещей в Objective-C, а теперь Swift, так как вы можете добавить код в класс или фреймворк, который вам не принадлежит.Следовательно, имеет смысл, что вы не должны «заменять» код в расширениях, говоря концептуально.

Именно поэтому компилятор жалуется, когда вы пытаетесь это сделать.

Также ознакомьтесь с этим ответом .

, но, похоже, это тоже проблема поддержки, так как быстрый компилятор просто выдает эту ошибку:

переопределение не-@ objc объявлений из расширений не поддерживается.

Согласно Apple,

Расширения могут добавлять новые функциональные возможности к типу, но они не могут переопределять существующие функциональные возможности..

Но это не так, поскольку мы переопределяем расширение, а не наоборот, что возвращает нас к объявлению extension.

Расширения.добавить новую функциональность к существующему классу, структуре, перечислению или типу протокола.Это включает в себя возможность расширять типы, для которых у вас нет доступа к исходному исходному коду (известный как ретроактивное моделирование).Расширения аналогичны категориям в Objective-C.(В отличие от категорий Objective C, расширения Swift не имеют имен.) Здесь .

Возвращаясь к устаревшей теме компилятор swift против компилятора Objc,

Динамическая отправка или Статическая отправка .

И от Apple нет официальной документации о том, почему это не поддерживается компилятором swift или у них есть какие-либо планы на будущее, чтобы это исправить или вообще считают это проблемой.

Однако , не существует такой вещи, как динамическая диспетчеризация Swift;у нас есть только динамическая диспетчеризация Objective-C.Это означает, что у вас не может быть только динамического, и вы должны написать @objc dynamic.Таким образом, это фактически та же самая ситуация, что и прежде, только что была сделана явной.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...