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


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

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

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

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

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

6 93

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

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

'super' members cannot be referenced in a root class

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

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

следующее скопировано из Swift-электронной книги 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.