我正在阅读Obj-C书,我并不完全了解最新情况。
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方法,如follow(创建副本并返回副本):
-(XYPoint*)origin{
if (origin){
XYPoint *copy = [[XYPoint alloc]init];
copy = origin;
NSLog(@"Copy will be returned");
return copy;
} else {
return origin;
}
}
但它仍然出现问题,输出相同,值不断变化。如何修改getter方法以防止这种情况发生?
为什么会这样?怎么预防这个? 任何建议都将不胜感激,谢谢!
答案 0 :(得分:1)
您已为origin
属性定义了您的setter,以便在设置后无法更改它。但是,您已定义XYPoint
以使其成为可变类(即您可以更改x
和y
值)。因此,当您返回theOrigin
[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
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];
还有其他方法,但我真的不喜欢你不会设定价值的制定者的做法。你可以做到这一点,但它不直观。作为开发人员,您希望在设置属性时,该属性实际上会发生变化。