objective c - Swift clase base nativa o NSObject
objective-c objective-c-runtime (6)
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 dinámico. Esto nos permite indicarle a Swift que un método debe usar despacho dinámico y, por lo tanto, admitirá la intercepción.
public dynamic func foobar() -> AnyObject {
}
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 dinámico en tiempo de ejecución se encuentra en el corazón de funciones como los observadores de propiedades, datos centrales, programació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?
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.
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 declaración 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 compilación
''super'' members cannot be referenced in a root class
Es normal. Mire los objetivos de diseño de Swift: el objetivo es hacer desaparecer grandes clases de problemas de programación. El Swizzling de métodos probablemente no sea una de las cosas que quiere hacer con Swift.
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_251Tambié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 codificación. Aquí hay un ejemplo.
En este ejemplo, donde no basamos en NSObject, el compilador 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 compilador 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!