2009-11-08 10 views
7

Puede declarar un método en Object-C y nombre cada parámetro dos veces, básicamente.Objective-C "mensajes": ¿cuál es la forma correcta de leerlo?

tengo la idea de que esto es de gran alcance, pero no estoy muy seguro de cómo usarlo sin embargo ...

Cuando John Kelly saluda:

[ p Greet:"John" toPerson:"Kelly" greetWith:"hey babe" ] ;

Algo sobre doesn leer de forma natural. No estoy seguro de que así sea como un programador objetivo-c experimentado escribiría ese "mensaje".

¿Alguien puede explicar el motivo de dos nombres para cada parámetro y posiblemente un ejemplo más útil de cómo se puede utilizar de manera efectiva para dar significado al programa?

También algo me molesta y que es el nombre del primer parámetro es básicamente el mismo que el nombre de la ' mensaje'. ¿Cómo lo resuelves al escribir un método significativo y comprensible/'nombres de mensajes'?

 
#import <Foundation/Foundation.h> 

@interface Person : NSObject 
{ 
} 

-(void)Greet:(char*)from toPerson:(char*)to greetWith:(char*)greeting ; 

@end 

@implementation Person 

-(void)Greet:(char*)from toPerson:(char*)to greetWith:(char*)greeting ; 
{ 
    printf("%s says %s to %s\n", from, greeting, to) ; 
} 

@end 



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


    Person * p = [ Person alloc ] ; 

    [ p Greet:"John" toPerson:"Kelly" greetWith:"hey babe" ] ; 
    [ p Greet:"Kelly" toPerson:"John" greetWith:"get bent" ] ; 

    [ p release ] ; 



    [pool drain]; 
    return 0; 
} 

+0

En cuanto a la edición: hice clic abajo por error cuando fui a favoritos, y luego no me permitió revertirlo (¿extraño error?). Edité tu respuesta para poder cambiarla. –

Respuesta

20

Lo primero es lo primero: como nota estilística, traen sus llaves juntas:

[ Person alloc ] 

debería ser

[Person alloc] 

También observo que estás olvidando para inicializar persona cuando lo asocie, debe usar:

Person *p = [[Person alloc] init]; 

Obtener la sensación de cómo declarar los métodos lleva un poco de tiempo. Examinar cómo el marco nombra sus métodos es útil. Para su ejemplo específico, creo que está sobreingeniería. Usted está buscando algo como esto:

Person *john = [[Person alloc] initWithName:@"John"]; 
Person *kelly = [[Person alloc] initWithName:@"Kelly"]; 

[john greetPerson:kelly withGreeting:@"Hey babe."]; 
[kelly greetPerson:john withGreeting:@"Get bent."]; 

en cuenta que no he activa los g en greetPerson, tampoco. Esa es una convención estilística de Objective-C.

No olvide que un objeto tiene su propia identidad, por lo que rara vez necesita dar instrucciones a un objeto (que representa a una persona) de quién es antes de hablar con alguien. Cuando escribe un mensaje, debe leer como en inglés. Cuando entra en múltiples argumentos - admito, raro - comience a pensar con comas:

[john sendEmailToPerson:kelly withSubject:subject body:body attachments:nil]; 

Vea cómo fluye eso? E incluso eso deja algo que desear, tampoco tengo esto dominado. Dale tiempo.

Un documento muy útil sobre esto es el Coding Guidelines for Cocoa de Apple.


Además, salga de la trampa C.Así es como me gustaría escribir todo el programa (estoy introduciendo un bote lleno de conceptos, por lo que no espero que entender todos de la misma):

#import <Foundation/Foundation.h> 

@interface Person : NSObject { 
    NSString *name; 
} 

@property (copy) NSString *name; 

- (id)init; 
- (id)initWithName:(NSString *)nm; 
- (void)greetPerson:(Person *)who withGreeting:(NSString *)grt; 

@end 

@implementation Person 
@synthesize name; 

- (id)init { 
    if (self = [super init]) { 
     name = @"James Bond";   // not necessary, but default 
    }         // values don't hurt. 
    return self; 
} 
- (id)initWithName:(NSString *)nm { 
    if (self = [self init]) { 
     name = [nm copy]; 
    } 
    return self; 
} 

- (void)greetPerson:(Person *)who withGreeting:(NSString *)grt { 
    NSLog(@"%@ says '%@' to %@", self.name, grt, who.name); 
} 

- (void)dealloc { 
    [name release]; 
    [super dealloc]; 
} 

@end 

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

    Person *john = [[Person alloc] initWithName:@"John"]; 
    Person *kelly = [[Person alloc] initWithName:@"Kelly"]; 

    [john greetPerson:kelly withGreeting:@"StackOverflow is great, isn't it?"]; 
    [kelly greetPerson:john withGreeting:@"Weren't we supposed to flirt?"]; 

    [john release]; 
    [kelly release]; 

    [pool drain]; 
    return 0; 
} 

Este código es completamente probado, por lo que si funciona sin engancho estaré debidamente impresionado.

+3

Las pautas de estilo de Apple sugieren que no debe usar "y" para las partes posteriores del nombre de su método. (Del documento que acaba de vincular: "No utilizar" y "para vincular las palabras clave que son atributos del receptor"). Por lo tanto, el selector debe ser simplemente 'sendEmailToPerson: withSubject: body: attachments:'. – Chuck

+2

@Chuck: ¿Ves? Te dije que no soy un experto. Editando. –

+2

Buena respuesta. Una nota adicional que ingresó en su código, pero no mencionó: La primera parte de un selector no debe estar en mayúscula. Entonces usted [john greetPerson] en lugar de [john GreetPerson:]. Sé que es quisquilloso, pero los programadores de Objective-C son muy particulares acerca de la sintaxis y las pautas de estilo. La capital Greet es muy de Java. – micmoo

2

La primera "parte" del método es selector, para su ejemplo esto incluye -greet:toPerson:greetWith:, este es el nombre real del método.

La segunda "parte" son los parámetros del método, en su ejemplo, son para, saludo.

Esto es similar a algo como C en la que tendría

int greet(string to, string greeting) { 
    print(greeting, to); 
} 

También debería mencionar, es muy probable va a querer trabajar con NSString * en lugar de char * y NSLog() en lugar de printf() (no hacer preocuparse, funciona casi exactamente igual).

0

Probablemente sería:

[personJohn greetPerson:@"Kelly" withGreeting:@"hey babe"]; 

El objeto persona ya está John y él está saludando a otro objeto persona, que yo no lo definiría como una cadena como lo hizo, sino como otra instancia de la clase Persona, y luego puedes hacer greetWithString.

[personJohn greetPerson:personKelly withGreeting:@"hey babe"]; 

No está definiendo los parámetros dos veces, ahí es donde está confundido. Si conoce C++, generalmente tiene:

void greetPerson(Person thePerson, string greeting); 

como prototipo de función, por ejemplo. De allí tendría que llamarlo así:

greetPerson(personKelly, "hey babe"); 

Ahora, todo Objective-C está haciendo es por lo que es fácil para ti por ser auto-documentado. En lugar de simplemente poner los parámetros de las funciones, que los nombra antes de que los estado, por lo que la llamada anterior sería:

greetPerson(Person:personKelly, greeting:"hey babe"); 

dado el prototipo de función publicado anteriormente. De esta forma, cuando lea el código, sabrá lo que hace cada parámetro y, por lo tanto, se documentará por sí mismo. Puede parecer tedioso al principio, pero la legibilidad del código aumenta mucho.

0

El nombre del método que describe arriba es "Greet: toPerson: greetWith:". Los dos puntos forman parte del nombre. Los parámetros (y sus especificadores de tipo) no lo son.

Estilo nota: no comience un nombre de método con una mayúscula a menos que usted se refiere a un acrónimo (como "URL".)

4

Otras personas han cubierto los puntos más importantes, así que voy a Sólo pesan sobre algunas de las preguntas complementarias:

también algo me molesta y que es el nombre del primer parámetro es básicamente el mismo que el nombre del 'mensaje'. ¿Cómo lo resuelves al escribir un método significativo y comprensible/'nombres de mensajes'?

La forma más común de resolver esto es hacer que el nombre del método sea una combinación de "lo que es/hace" y la etiqueta del primer parámetro. Ejemplo:

NSColor * color = [NSColor colorWithDeviceRed:0.5 green:0.5 blue:0.5 alpha:0.5]; 

¿Puede alguien explicar la razón de dos nombres para cada parámetro y, posiblemente, un ejemplo más útil de cómo se puede utilizar con eficacia para dar significado en el programa?

La respuesta rápida es que los dos nombres están destinados a diferentes públicos; uno es para el usuario del método, el otro es para el autor del método. Considera el ejemplo anterior nuevamente. La declaración de método es el siguiente:

+ (NSColor *)colorWithDeviceRed:(CGFloat)red 
          green:(CGFloat)green 
          blue:(CGFloat)blue 
          alpha:(CGFloat)alpha 

Cuando un usuario llama a este método, que se ocupan de las primeras etiquetas (las de antes de los dos puntos). Puede ver en mi primer ejemplo, donde los valores del canal se pasan como constantes numéricas, que solo las etiquetas se ven en el código.

Los nombres de los parámetros reales (las partes después de que el tipo), se utilizan dentro la definición del método, y como tales son en realidad sólo existe para el programador que escribe el método, ya que esas son las variables que estarán disponibles dentro de el cuerpo del método en sí mismo.

+0

Vea también: http://stackoverflow.com/questions/683211/method-syntax-in-objective-c –

Cuestiones relacionadas