He leído las preguntas ya publicadas extensamente y no puedo encontrar la respuesta que estoy buscando.Objetivo C - Accessors ie Getters/Setters
entiendo totalmente el concepto de usar la directiva @syntesize
para crear métodos getter y setter (es decir, si tuviera @property int width
y @synthesize width
, estoy inadvertidamente creando un método de obtención de width
y un método de selección de setWidth:
).
Sin embargo, cuando no estoy usando la directiva @synthesize
pero declaro variables de instancia en la sección @implementation
que son objetos, no entiendo completamente cómo funcionan los métodos de acceso. Esto es lo que no entiendo de la siguiente código:
1) en main
donde dice:
NSLog(@"Origin at (%i, %i)", myRect.origin1.x, myRect.origin1.y);
Me parece como si fuera a estar llamando el método [[myRect origin1] x]
que primero determinar que [myRect origin1]
devuelve origin
y luego llamará inmediatamente al [origin x]
como resultado (y luego haga lo mismo para y
). Ahora, lo que me arroja es el hecho de que si tuviera que cambiar el nombre del método getter
-(XYpoint *) origin1;
contenido dentro Rectangle.h a
-(XYpoint *) origin2;
el programa recibe montones de errores y deja de compilar. Nota: También ha cambiado el nombre de este método en todas partes se hace referencia incluyendo el cambio del código anterior en el principal a
NSLog(@"Origin at (%i, %i)", myRect.origin2.x, myRect.origin2.y);
Sin embargo, si yo también cambiar el nombre del método de selección de:
-(void) setOrigin1: (XYpoint *) pt
a :
-(void) setOrigin2: (XYpoint *) pt
todo funciona como antes. Me parece que solo funciona correctamente cuando mi getter y setter son nombrados en la convención de nomenclatura x
setX
. Supongo que esto es principalmente lo que necesito explicar:
A) Si creo una variable de instancia que resulta ser un objeto (como 'origen' en este caso), ¿debo crear métodos getter y setter para ello?
B) ¿Puedo crear un método getter pero no es un método de selección o viceversa
C) ¿Es obligatorio que si hago crear tanto un captador y el método de selección de 'origen' que ambos se nombran en la manera x
setX
. En este caso como -(XYpoint *) origin1
y -(void) setOrigin1: (XYpoint *) pt
. Como en el caso de que cambie el nombre del getter, ¿debo cambiar el nombre del setter en consecuencia?
Aquí es todo el código:
Rectangle.h:
#import <Foundation/Foundation.h>
@class XYpoint;
@interface Rectangle : NSObject
@property int width, height;
-(XYpoint *) origin1;
-(void) setOrigin1: (XYpoint *) pt;
-(void) setWidth: (int) w andHeight: (int) h;
-(int) area;
-(int) perimeter;
@end
rectángulo.m:
#import "Rectangle.h"
@implementation Rectangle
{
XYpoint *origin;
}
@synthesize width, height;
-(void) setWidth:(int) w andHeight:(int)h
{
width = w;
height = h;
}
-(void) setOrigin1: (XYpoint *) pt
{
origin = pt;
}
-(int) area
{
return width * height;
}
-(int) perimeter
{
return (width + height) * 2;
}
-(XYpoint *) origin1
{
return origin;
}
@end
XYpoint.h:
#import <Foundation/Foundation.h>
@interface XYpoint : NSObject
@property int x, y;
-(void) setX: (int) xVal andY: (int) yVal;
@end
XYpoint.m:
#import "XYpoint.h"
@implementation XYpoint
@synthesize x,y;
-(void) setX: (int) xVal andY: (int) yVal
{
x = xVal;
y = yVal;
}
@end
main.m:
#import <Foundation/Foundation.h>
#import "Rectangle.h"
#import "XYpoint.h"
int main (int argc, const char * argv[])
{
@autoreleasepool {
Rectangle *myRect = [[Rectangle alloc] init];
XYpoint *myPoint = [[XYpoint alloc] init];
[myPoint setX: 100 andY: 200];
[myRect setWidth: 5 andHeight:8];
myRect.origin1 = myPoint;
NSLog(@"Rectangle w = %i, h = %i", myRect.width, myRect.height);
NSLog(@"Origin at (%i, %i)", myRect.origin1.x, myRect.origin1.y);
NSLog(@"Area = %i, Perimeter = %i", [myRect area], [myRect perimeter]);
}
return 0;
}
La notación de puntos es en realidad solo una abreviatura de las llamadas de acceso. Dado que myRect.origin2 podría equivaler a [myRect origin2] O [myRect setOrigin2], según el contexto, ambos accesores deben definirse para poder utilizar la notación de puntos. De todos modos, deberías declarar las variables de instancia como propiedades, como en la respuesta de Jakob. – spwert
¡Gracias! Ese es exactamente mi problema. Cambiar mi getter (o setter) de setOrigin1 a setOrigin2 significaría que cuando se llama myRect.origin1, esencialmente necesita un getter/setter nombrado en consecuencia. Y desde que cambié setOrigin1 a setOrigin2, ya no hay tanto getter como setter. Incluso si nunca lo uso, el compilador lo requiere. Al menos creo que eso es lo que quieres decir. Si es así, tiene sentido para mí ahora. Aunque no sé cómo darle una respuesta "correcta" ya que solo aparece como un comentario – ReiAndCoke
Esto está mal. No necesita ambos accesorios. Si define '- (int) foo;' en su archivo de encabezado, puede usar 'int x = myObj.foo;'. Por otro lado, si define '- (void) setBar: (int) anInt;' en el archivo de encabezado, puede usar 'myObj.bar = 15;'. Getters y setters son independientes. –