Swift isa-переназначение указателя или другой поддерживаемый метод swizzling

У классов Swift есть что-то вроде указателя isa, который можно переназначить?

Мы видели, что Swift использует более статический метод отправки, чем objective-C, который (если только класс dervices из Foundation/NSObject) не предотвращает стиль swizzling основанный на реализации методов переопределения во время выполнения.

Мне интересно, как мы будем использовать динамические функции на основе перехвата меток, такие как шаблон наблюдателя, уведомления и т.д.? В настоящее время все эти материалы предоставляются слоем Objective-C и могут быть легко интегрированы в Swift. Но, если мы хотим предоставить эти функции в рамках (или приложениях) наших собственных, необходимо ли их реализовать в Objective-C? Я бы предположил, что есть способ сделать это "изначально".

Другой вид swizzling, общий для Objective-C, переназначает isa-указатель для генерации подкласса "на лету". Этот вид swizzling поддерживается в Swift? Если не существует поддерживаемый способ перехвата произвольных вызовов метода?

Изменить: Как указывает @jatoben, с arm64 isa-переназначение должно выполняться вызовом object_setClass(), а не путем прямого доступа к значению. Это по-прежнему называется "isa pointer swizzling"

Ответ 1

Похоже, что и обмен методой, и метод переопределения указателя isa работают только в том случае, если класс Swift имеет NSObject в качестве суперкласса (прямо или вверх). В настоящее время он не работает, когда класс Swift не имеет суперкласса или какого-либо другого базового класса, отличного от Foundation.

Следующий тест показывает это:

Класс: Птичка

class Birdy: NSObject {    
    func sayHello()
    {
        println("tweet tweet")
    }    
}

Класс: HodorBirdy

class HodorBirdy: Birdy {

    override func sayHello()
    {
        super.sayHello()
        println("hodor hodor")
    }
}

Тест:

func testExample() {        
    var birdy : Birdy = Birdy()
    object_setClass(birdy, HodorBirdy.self)
    birdy.sayHello();
}

И результат был таким, как ожидалось:

tweet tweet
hodor hodor

В этом тесте оба базового класса и подкласса были созданы заранее. Хотя они также могут быть созданы динамически с использованием среды выполнения Objective-C, пока класс NSObject является предком.

Если класс Swift не основан на фундаменте Objective-C, тогда компилятор будет поддерживать отправку на основе статики или vtable, поэтому неясно, как в этом случае будет работать перехват методов!

Если язык/компилятор не дает конкретного разрешения на это, мы будем выступать за динамизм в пользу производительности. (Перехват, который является основой "динамического" поведения, может быть выполнен либо во время компиляции, либо во время выполнения. В случае статической или виртуальной отправки без виртуальной машины применяется только время компиляции.

Ответ 2

Я не могу ответить на ваш вопрос о быстром эквиваленте "isa", но я думаю, что знаю часть ответа на ваш основной вопрос.

Собственные наблюдатели кажутся встроенными средствами для шаблона наблюдателя. Вместо обнаружения времени "тип" (RTTI, what-have-you) оно соткано в явном виде.

Из языка "Быстрый язык программирования" стр. 345:

Наблюдатели свойств наблюдают и реагируют на изменения в свойствах стоимость. Наблюдатели свойств вызывается каждый раз, когда значение свойства set, даже если новое значение совпадает с текущим значением свойства значение.

Вы можете добавить наблюдателей свойств к любым сохраненным свойствам, которые вы определяете, кроме ленивых хранимых свойств. Вы также можете добавить наблюдателей свойств к любому унаследованному свойству (независимо от того, хранятся или вычисляются) путем переопределения свойство в подклассе.

У вас есть возможность определить одного или обоих этих наблюдателей на Свойство:

  • willSet вызывается непосредственно перед сохранением значения.
  • didSet вызывается сразу после сохранения нового значения.

Я не уверен, как все это сработает, но я заинтригован.

Полагая, что обнаружение типа времени выполнения также, похоже, противоречит сильной ортодоксии статического типа.