2009-11-08 14 views
6

de Objective-C utiliza enlace dinámico: es decir las llamadas a métodos se resuelven en tiempo de ejecución.unión dinámica parece como una mentira

Bien.

Y use of dot notation really boils down to a method call

Pero, ¿por qué entonces, no me puede hacer algo como esto:

 
#import <Foundation/Foundation.h> 

int main (int argc, const char * argv[]) { 
    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; 


    // Intercept the exception 
    @try 
    { 
    @throw [ NSException 
      exceptionWithName:@"Exception named ME!" 
      reason:@"Because i wanted to" 
      userInfo:nil ] ; 
    } 
    @catch(id exc) // pointer to an exception object? 
    { 



    //NSLog(@"%@ : %@\n", exc.name, exc.reason) ; // ILLEGAL: Request for member 
    // 'name' in something not a structure or union.. 
    // If objective-c uses dynamic binding, and dot notation 
    // boils down to calling the getter, then 
    // WHY do I have to cast to the concrete type here? 

    // Only works if I cast to the concrete type NSException* 
    NSException* nexc = (NSException*)exc ; 
    NSLog(@"%@ : %@\n", nexc.name, nexc.reason) ; 



    } 



    [pool drain]; 
    return 0; 
} 

Cuando escucho "Enlace dinámico" Estoy pensando en "lo que debe comportarse como una scripting language ", y me sorprende la inflexibilidad de Objective-C en comparación con un lenguaje de scripting como JavaScript.

+2

Estás confundiendo el enlace dinámico con el pastel. El pastel es una mentira. –

+1

_ "Las llamadas al método se resuelven en tiempo de ejecución" _ realmente debería considerarse como _ "el envío de mensajes ocurre en el tiempo de ejecución" _. El uso del _dot operator_ completo es más un hack que cualquier otra cosa. –

+2

No hay nada de hackish al respecto; es un sinónimo muy bien definido para una llamada de método con una restricción adicional que el tipo debe ser bien conocido. (Si a alguien le gusta o no el punto o piensa que es una buena adición, es una opinión completa, sin comentarios :). – bbum

Respuesta

17

Usted está confundiendo el tiempo de ejecución y el compilador. El tiempo de ejecución no tiene ningún problema para hacer frente a eso. El problema es que la notación de puntos (que es azúcar sintáctica) requiere información de tipo para que el compilador elimine la ambigüedad entre los objetos de Objective-C y las estructuras de C.

Si no se utiliza la notación de puntos funciona:

NSLog(@"%@ : %@\n", [exc name], [exc reason]) ; 

Lo anterior generará una advertencia si el tipo no es de identificación ya que el compilador sabe que lo hace saber el tipo y no puede garantizar el envío funcionará, pero se compilará y ejecutará.

Fundamentalmente el problema es que el compilador necesita saber si generar una carga de estructura o un despacho de Objective C, en otras palabras, con notación de puntos necesita tener suficiente información para determinar la diferencia entre un objeto y un objeto tipo escalar

0

Objective-C es compatible con enlace dinámico. Sin embargo, no puede usar propiedades en objetos de tipo 'id', pero puede enviarle cualquier mensaje que desee. (Esto es probablemente un error en la actual definición/implementación ... Pero dejemos eso de lado por ahora.)

Si lo hizo

NSLog(@"%@ : %@", [exc name], [exc reason]); 

entonces sería trabajar. Tenga en cuenta que no necesita poner una nueva línea en una declaración NSLog, ya que todos están en líneas separadas de todos modos.

+2

Asegúrate de leer la respuesta de bbum. La implementación no es un error, sino a propósito. – danimal

+0

Lo suficientemente, debe haber respondido alrededor del mismo tiempo :-) – AlBlue

17

vinculante dinámico no es también tipado dinámico. C es un lenguaje fuertemente tipado y, en particular, el tipo de argumento o valor de retorno es crítico y puede afectar significativamente la generación de código.

Propiedades están específicamente diseñados para eliminar la ambigüedad. Como parte de eso, se tomó la decisión de no permiten la sintaxis con punto para ser utilizado en contra id.

En concreto, se aborda esta situación:

@interface Foo 
- (short) length; 
@end 

@interface Bar 
- (unsigned long long) length; 
@end 

Teniendo en cuenta lo anterior en dos ficheros de cabeceras, compilación de [anObject length] dará una advertencia única de los dos archivos de cabecera se han importado. Si solo se ha importado un archivo de encabezado, el sitio de la llamada se compilará devolviendo el tipo que se ve en el encabezado. Si el sitio llamado fuera por el método otra, un resultado muy inesperado sería devuelta.

La limitación en la sintaxis de punto elimina esta posible ambigüedad. Esta es también la razón por la que no generalmente ve declaraciones de métodos co-variantes. El C ABI simplemente no lo admite limpiamente (dicho esto, Objective-C hace un mal trabajo apoyando la co-varianza del tipo de objeto).

En realidad, los desarrolladores de Objective-C raramente usan el tipo id. Las declaraciones de tipos específicos permiten al compilador mejorar significativamente su validación de código.

+0

Excelente respuesta como de costumbre, Bill! Siempre es bueno saber sobre los detalles de las decisiones de diseño. Y acepto, uso 'id' con moderación, ya que a menudo prefiero los beneficios de la tipa estática cuando puedo obtenerla. –

Cuestiones relacionadas