首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >理解getter和setter例程

理解getter和setter例程
EN

Stack Overflow用户
提问于 2015-01-30 06:22:04
回答 1查看 90关注 0票数 0

我正在读Obj的书,我不完全理解发生了什么。

main.m函数中有我的应用程序的代码:

代码语言:javascript
运行
复制
    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);

你看,我插入了以下代码:

代码语言:javascript
运行
复制
 XYPoint *theOrigin = [myRect origin];

        [theOrigin setX:200];
        [theOrigin setY:300];

我这样做是有目的的,实际上,我不想改变这些价值观。在Rectangle.m文件中,我修改了setter方法如下:

代码语言:javascript
运行
复制
-(void)setOrigin:(XYPoint *)pt{ 
    if (!origin){  
        origin = [[XYPoint alloc]init];
        origin.x = pt.x;
        origin.y = pt.y;
    }
}

因此,逻辑是,当原点不是零时,它就不能改变(如果我理解正确的话)。但是NSLog的输出值仍然是200和300,因此,在第一次声明之后,它改变了吗?

当尝试像这样修改我的XYPoint类时:

代码语言:javascript
运行
复制
[myPoint setX:50 andY:50];
NSLog(@"Origin at (%i, %i)", myRect.origin.x, myRect.origin.y);

我得到了同样的输出。这让人困惑。

我尝试修改getter方法,如下所示(创建副本并返回副本):

代码语言:javascript
运行
复制
-(XYPoint*)origin{

    if (origin){
        XYPoint *copy = [[XYPoint alloc]init];
        copy = origin;
        NSLog(@"Copy will be returned");
        return copy;
    }   else {
        return  origin;
    }
}

但是这里仍然出现了这个问题,并且输出的值也在不断变化。如何修改getter方法以防止这种情况发生?

为什么会发生这种事?如何防止这种情况发生?任何建议都将不胜感激,谢谢!

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2015-01-30 07:27:35

您已经为origin属性定义了setter,这样一旦设置了它,就不能更改它。但是您已经定义了XYPoint,因此它是一个可变的类(也就是说,您可以更改xy值)。因此,当您返回theOrigin of [myRect origin]时,仍然能够更改其值。

就我个人而言,我会从这个界面后退一步。我不喜欢类接口,它建议您可以在真正不能设置的时候设置一些属性。我也不喜欢setOrigin正在使用类似于copy内存语义的东西这个事实,但是您还没有共享一个使这个意图明确的属性定义。

但是回到我假设的意图,不让origin在设置之后改变,我宁愿看到您在实例化对象时设置这些属性,然后将它们保留为readonly,这样您就可以确信它们不会在您身上发生变化。最终的结果是一组完全直观的类。

因此:

代码语言:javascript
运行
复制
@interface XYPoint : NSObject

@property (nonatomic, readonly) CGFloat x;
@property (nonatomic, readonly) CGFloat y;

- (instancetype)initWithX:(CGFloat)x y:(CGFloat)y;

@end

哪里

代码语言:javascript
运行
复制
@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

代码语言:javascript
运行
复制
@interface Rectangle : NSObject

@property (nonatomic, readonly) XYPoint *origin;

- (instancetype)initWithOrigin:(XYPoint *)origin;

@end

哪里

代码语言:javascript
运行
复制
@implementation Rectangle

- (instancetype)initWithOrigin:(XYPoint *)origin {
    self = [super init];
    if (self) {
        _origin = origin;
    }
    return self;
}

@end

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

代码语言:javascript
运行
复制
XYPoint *origin = [[XYPoint alloc] initWithX:100 y:200];
Rectangle *rect = [[Rectangle alloc] initWithOrigin:origin];

还有其他的方法,但我真的不喜欢你的方法,一个不会设定价值的策划者。你可以这么做,但这是不直观的。作为开发人员,您希望在设置属性时,该属性实际上会发生更改。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/28230312

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档