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

я протестировал некоторые Иса группирующее С Swift и обнаружил, что он работает только тогда, когда NSObject является супер-классом (напрямую или далее) или с помощью украшения "@objc". В противном случае он будет следовать стилю static - и vtable-dispatch, например C++.

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

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

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

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

6 ответов


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 {
}

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


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

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

из ссылки на язык:

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

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

'super' members cannot be referenced in a root class

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

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


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

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

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

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


ссылка

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

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