了解getter和setter例程

时间:2015-01-30 06:22:05

标签: objective-c

我正在阅读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方法以防止这种情况发生?

为什么会这样?怎么预防这个? 任何建议都将不胜感激,谢谢!

1 个答案:

答案 0 :(得分:1)

您已为origin属性定义了您的setter,以便在设置后无法更改它。但是,您已定义XYPoint以使其成为可变类(即您可以更改xy值)。因此,当您返回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

然后,一旦创建了XYPointRectangle个对象,就可以确信属性不会发生变异。

XYPoint *origin = [[XYPoint alloc] initWithX:100 y:200];
Rectangle *rect = [[Rectangle alloc] initWithOrigin:origin];

还有其他方法,但我真的不喜欢你不会设定价值的制定者的做法。你可以做到这一点,但它不直观。作为开发人员,您希望在设置属性时,该属性实际上会发生变化。