it-swarm.com.ru

Swift собственный базовый класс или NSObject

Я протестировал некоторые isa swizzling со Swift и обнаружил, что он работает только тогда, когда NSObject является суперклассом (напрямую или далее) или с использованием декорации '@objc'. В противном случае он будет следовать стилю диспетчеризации статических и виртуальных таблиц, например C++.

Нормально ли определять класс Swift без базового класса Cocoa/NSObject? Если это меня беспокоит, это означает отказ от большей части динамизма Objective-C, такого как перехват методов и интроспекция во время выполнения.

Динамическое поведение во время выполнения лежит в основе таких функций, как наблюдатели свойств, Базовые данные, Аспектно-ориентированное программирование , Обмен сообщениями более высокого порядка , аналитические структуры и каркасы журналов и так далее.

Использование стиля вызова метода в Objective-C добавляет около 20 операндов машинного кода к вызову метода, поэтому в определенных ситуациях ( много сложных вызовов методов с маленькими телами Статическая и виртуальная диспетчеризация в стиле C++ может работать лучше.

Но, учитывая общее правило 95-5 ( 95% прироста производительности происходит при настройке 5% кода ), не имеет смысла начинать с мощными динамическими характеристиками и укрепить в случае необходимости?

98
Jasper Blues

Swift классы, которые являются подклассами NSObject:

  • сами классы Objective-C
  • используйте objc_msgSend() для вызовов (большинства) их методов
  • предоставить метаданные времени выполнения Objective C для (большей части) их реализаций метода

Swift классы, которые не являются подклассами NSObject:

  • являются классами Objective-C, но реализуют лишь несколько методов для совместимости с NSObject
  • не используйте objc_msgSend() для вызовов их методов (по умолчанию)
  • не предоставляют метаданные времени выполнения Objective C для их реализаций метода (по умолчанию)

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

Edit:

С Xcode 6 beta 6 появляется динамический атрибут. Это позволяет нам указывать Swift, что метод должен использовать динамическую диспетчеризацию и поэтому будет поддерживать перехват.

public dynamic func foobar() -> AnyObject {
}
98
Greg Parker

Я также обнаружил, что, если базировать класс Swift на NSObject, я увидел неожиданное поведение во время выполнения, которое могло скрыть ошибки кодирования. Вот пример.

В этом примере, где мы не основаны на NSObject, компилятор правильно обнаруживает ошибку в testIncorrect_CompilerShouldSpot, сообщая, что "... 'MyClass' не может быть преобразован в 'MirrorDisposition'"

class MyClass {
  let mString = "Test"

  func getAsString() -> String {
    return mString
  }

  func testIncorrect_CompilerShouldSpot() {
    var myString = "Compare to me"
      var myObject = MyClass()
      if (myObject == myString) {
        // Do something
      }
  }

  func testCorrect_CorrectlyWritten() {
    var myString = "Compare to me"
      var myObject = MyClass()
      if (myObject.getAsString() == myString) {
        // Do something
      }
  }
}

В этом примере, где мы опираемся на NSObject, компилятор не обнаруживает ошибку в testIncorrect_CompilerShouldSpot:

class myClass : NSObject {
  let mString = "Test"

  func getAsString() -> String {
    return mString
  }

  func testIncorrect_CompilerShouldSpot() {
    var myString = "Compare to me"
      var myObject = MyClass()
      if (myObject == myString) {
        // Do something
      }
  }

  func testCorrect_CorrectlyWritten() {
    var myString = "Compare to me"
      var myObject = MyClass()
      if (myObject.getAsString() == myString) {
        // Do something
      }
  }
}

Я предполагаю, что мораль, только основываться на NSObject, где вы действительно должны!

14
Pete

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

Обратите внимание, что исключение суперкласса из объявления класса не назначает неявный базовый суперкласс любого вида. Он определяет базовый класс, который фактически станет корнем для независимой иерархии классов.

Из языковой справки:

Классы Swift не наследуются от универсального базового класса. Классы, которые вы определяете без указания суперкласса, автоматически становятся базовыми для вас.

Попытка ссылки на super из класса без суперкласса (то есть базового класса) приведет к ошибке времени компиляции

'super' members cannot be referenced in a root class
12
Cezar

Я считаю, что подавляющее большинство данных Swift не будет objc. Только те части, которые должны взаимодействовать с инфраструктурой Objective C, будут явно помечены как таковые.

Насколько интроспекция во время выполнения будет добавлена ​​к языку, я не знаю. Перехват метода, вероятно, станет возможным только в том случае, если метод явно разрешает это. Это мое предположение, но только дизайнеры языка в Apple действительно знают, куда они направляются.

1
Analog File