Swift clase base nativa o NSObject

Probé un poco de swizzling con Swift, y descubrí que solo funciona cuando NSObject es una súper clase (directamente o más arriba), o usando la decoración ‘@objc’. De lo contrario, seguirá un estilo de despacho estático y vtable, como C ++.

¿Es normal definir una clase Swift sin una clase base Cocoa / NSObject? Si me preocupa, esto significa renunciar a gran parte del dinamismo de Objective-C, como la interceptación del método y la introspección en tiempo de ejecución.

El comportamiento dynamic en tiempo de ejecución se encuentra en el corazón de funciones como los observadores de propiedades, datos centrales, progtwigción orientada a aspectos , mensajería de orden superior , marcos analíticos y de registro, etc.

El uso del estilo de invocación de método de Objective-C agrega alrededor de 20 operandos de código de máquina a una llamada de método, por lo que en ciertas situaciones ( muchas llamadas apretadas a métodos con cuerpos pequeños ) el envío de estática y vtable de estilo C ++ puede funcionar mejor.

Pero dada la regla general de 95-5 (el 95% de las ganancias de rendimiento provienen del ajuste del 5% del código ), ¿no tiene sentido comenzar con las poderosas características dinámicas y endurecerse cuando sea necesario?

Clases de Swift que son subclases de NSObject:

  • son las clases Objective-C en sí
  • use objc_msgSend() para llamadas a (la mayoría de) sus métodos
  • proporcionar metadatos de tiempo de ejecución de Objective-C para (la mayoría de) sus implementaciones de métodos

Clases Swift que no son subclases de NSObject:

  • son clases Objective-C, pero implementan solo un puñado de métodos para compatibilidad con NSObject
  • no use objc_msgSend() para las llamadas a sus métodos (por defecto)
  • no proporcione metadatos de tiempo de ejecución de Objective-C para sus implementaciones de métodos (por defecto)

Subclasificar NSObject en Swift le ofrece la flexibilidad de tiempo de ejecución Objective-C pero también el rendimiento de Objective-C. Evitar NSObject puede mejorar el rendimiento si no necesita la flexibilidad de Objective-C.

Editar:

Con Xcode 6 beta 6, aparece el atributo dynamic. Esto nos permite indicarle a Swift que un método debe usar despacho dynamic y, por lo tanto, admitirá la intercepción.

 public dynamic func foobar() -> AnyObject { } 

También descubrí que si basaba una clase Swift en NSObject, veía un comportamiento inesperado en tiempo de ejecución que podía ocultar errores de encoding. Aquí hay un ejemplo.

En este ejemplo, donde no basamos en NSObject, el comstackdor detecta correctamente el error en testIncorrect_CompilerShouldSpot, informando que “… ‘MyClass’ no es convertible a ‘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 } } } 

En este ejemplo, donde basamos en NSObject , el comstackdor no detecta el error en 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 } } } 

¡Supongo que la moraleja es solo base en NSObject donde realmente tienes que hacerlo!

De acuerdo con la referencia del lenguaje, no es necesario que las clases subclasesen ninguna clase de raíz estándar, por lo que puede incluir u omitir una superclase según sea necesario.

Tenga en cuenta que al omitir una superclase de la statement de clase, no se asigna una superclase base implícita de ningún tipo. Define una clase base, que se convertirá efectivamente en la raíz de una jerarquía de clases independiente.

De la referencia de idioma:

Las clases Swift no heredan de una clase base universal. Las clases que define sin especificar una superclase se convierten automáticamente en clases base para que pueda construir.

Intentar hacer referencia a super de una clase sin una superclase (es decir, una clase base) dará como resultado un error de tiempo de comstackción

 'super' members cannot be referenced in a root class 

Creo que la gran mayoría de los datos de Swift no serán objc . Solo aquellas partes que sí necesitan comunicarse con la infraestructura del Objetivo C se marcarán explícitamente como tales.

Hasta qué punto la introspección del tiempo de ejecución se agregará al idioma, no lo sé. La interceptación del método probablemente solo será posible si el método lo permite explícitamente. Esta es mi suposición, pero solo los diseñadores de lenguaje dentro de Apple realmente saben a dónde se dirigen realmente.

Lo siguiente se copió del eBook-eBook de Apple y da una respuesta adecuada a su pregunta:

Definición de una clase base

Cualquier clase que no hereda de otra clase se conoce como clase base.

Las clases Swift no heredan de una clase base universal. Las clases que define sin especificar una superclase se convierten automáticamente en clases base para que pueda construir.

Referencia

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

Es normal. Mire los objectives de diseño de Swift: el objective es hacer desaparecer grandes clases de problemas de progtwigción. El Swizzling de métodos probablemente no sea una de las cosas que quiere hacer con Swift.