Быстрый базовый класс Swift или NSObject

Я проверил несколько isa swizzling с помощью Swift и обнаружил, что он работает только в том случае, если NSObject является суперклассом (напрямую или дальше) или с помощью Украшение '@objc'. В противном случае он будет следовать статическому и vtable-отправке, например, С++.

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

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

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

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

Ответ 1

Классы 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 появляется динамический атрибут. Это позволяет нам проинструктировать Свифта о том, что метод должен использовать динамическую отправку и, следовательно, поддерживать перехват.

public dynamic func foobar() -> AnyObject {
}

Ответ 2

Я также обнаружил, что, основываясь на классе 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, где вам действительно нужно!

Ответ 3

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

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

С помощью ссылки на язык:

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

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

'super' members cannot be referenced in a root class

Ответ 4

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

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

Ответ 5

Следующее копируется из Apple Swift-eBook и дает соответствующий ответ на ваш вопрос:

Определение базового класса

Любой класс, который не наследуется от другого класса, известен как базовый класс.

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


Ссылка

https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Inheritance.html#//apple_ref/doc/uid/TP40014097-CH17-XID_251

Ответ 6

Это нормально. Посмотрите на цели разработки Swift: цель состоит в том, чтобы устранить огромные классы проблем программирования. Метод swizzling, вероятно, не является одной из вещей, которые вы хотите сделать с Swift.