我正在读Obj的书,我不完全理解发生了什么。
在main.m函数中有我的应用程序的代码:
Rectangle *myRect = [[Rectangle alloc]init];
XYPoint *myPoint = [[XYPoint alloc]init];
[myPoint setX:100 andY:200];
myRect.origin = myPoint;
XYPoint *theOrigin = [myRect origin];
[theOrigin setX:200];
[theOrigin setY:300];
NSLog(@"Test %i and %i", theOrigin.x, theOrigin.y);
NSLog(@"Origin at (%i, %i)", myRect.origin.x, myRect.origin.y);你看,我插入了以下代码:
XYPoint *theOrigin = [myRect origin];
[theOrigin setX:200];
[theOrigin setY:300];我这样做是有目的的,实际上,我不想改变这些价值观。在Rectangle.m文件中,我修改了setter方法如下:
-(void)setOrigin:(XYPoint *)pt{
if (!origin){
origin = [[XYPoint alloc]init];
origin.x = pt.x;
origin.y = pt.y;
}
}因此,逻辑是,当原点不是零时,它就不能改变(如果我理解正确的话)。但是NSLog的输出值仍然是200和300,因此,在第一次声明之后,它改变了吗?
当尝试像这样修改我的XYPoint类时:
[myPoint setX:50 andY:50];
NSLog(@"Origin at (%i, %i)", myRect.origin.x, myRect.origin.y);我得到了同样的输出。这让人困惑。
我尝试修改getter方法,如下所示(创建副本并返回副本):
-(XYPoint*)origin{
if (origin){
XYPoint *copy = [[XYPoint alloc]init];
copy = origin;
NSLog(@"Copy will be returned");
return copy;
} else {
return origin;
}
}但是这里仍然出现了这个问题,并且输出的值也在不断变化。如何修改getter方法以防止这种情况发生?
为什么会发生这种事?如何防止这种情况发生?任何建议都将不胜感激,谢谢!
发布于 2015-01-30 07:27:35
您已经为origin属性定义了setter,这样一旦设置了它,就不能更改它。但是您已经定义了XYPoint,因此它是一个可变的类(也就是说,您可以更改x和y值)。因此,当您返回theOrigin of [myRect origin]时,仍然能够更改其值。
就我个人而言,我会从这个界面后退一步。我不喜欢类接口,它建议您可以在真正不能设置的时候设置一些属性。我也不喜欢setOrigin正在使用类似于copy内存语义的东西这个事实,但是您还没有共享一个使这个意图明确的属性定义。
但是回到我假设的意图,不让origin在设置之后改变,我宁愿看到您在实例化对象时设置这些属性,然后将它们保留为readonly,这样您就可以确信它们不会在您身上发生变化。最终的结果是一组完全直观的类。
因此:
@interface XYPoint : NSObject
@property (nonatomic, readonly) CGFloat x;
@property (nonatomic, readonly) CGFloat y;
- (instancetype)initWithX:(CGFloat)x y:(CGFloat)y;
@end哪里
@implementation XYPoint
- (instancetype)initWithX:(CGFloat)x y:(CGFloat)y {
self = [super init];
if (self) {
_x = x;
_y = y;
}
return self;
}
@end同样,我倾向于把origin of Rectangle变成readonly。
@interface Rectangle : NSObject
@property (nonatomic, readonly) XYPoint *origin;
- (instancetype)initWithOrigin:(XYPoint *)origin;
@end哪里
@implementation Rectangle
- (instancetype)initWithOrigin:(XYPoint *)origin {
self = [super init];
if (self) {
_origin = origin;
}
return self;
}
@end然后,一旦创建了XYPoint和Rectangle对象,就可以确信这些属性不会发生变异。
XYPoint *origin = [[XYPoint alloc] initWithX:100 y:200];
Rectangle *rect = [[Rectangle alloc] initWithOrigin:origin];还有其他的方法,但我真的不喜欢你的方法,一个不会设定价值的策划者。你可以这么做,但这是不直观的。作为开发人员,您希望在设置属性时,该属性实际上会发生更改。
https://stackoverflow.com/questions/28230312
复制相似问题