2015-01-30 2 views
0

Obj-C 서적을 읽는 중이고 계속 진행되고 있습니다.getter 및 setter 루틴 이해

main.m 기능에서 내 응용 프로그램의 코드가있다 :

XYPoint *theOrigin = [myRect origin]; 

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

내가 실제로, 나는 싶지 않았다 목적으로했다 :

당신이 볼
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); 

, 내가 다음 코드를 삽입 변경할 값. Rectangle.m 파일에서 나는 다음과 세터 방법을 수정 :

-(void)setOrigin:(XYPoint *)pt{ 
    if (!origin){ 
     origin = [[XYPoint alloc]init]; 
     origin.x = pt.x; 
     origin.y = pt.y; 
    } 
} 

기원이 0이 아닌 경우 (내가 올바른 이해한다면) 그래서 논리는, 변경할 수 없습니다. 그러나 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 메소드를 수정하는 방법은 무엇입니까?

왜 그런가요? 이것을 방지하는 방법? 조언을 주시면 감사하겠습니다.

답변

1

설정 한 후에는 변경할 수없는 origin 속성에 대한 설정기를 정의했습니다. 그러나 XYPoint을 변경 가능한 클래스로 정의했습니다 (예 : xy 값을 변경할 수 있음). 따라서 theOrigin[myRect origin] 인 경우에도 값을 변경할 수 있습니다.


개인적으로 나는이 인터페이스에서 뒤로 물러났다. 나는 정말로 할 수 없을 때 당신이 어떤 속성을 설정할 수 있다고 제안하는 클래스 인터페이스의 팬이 아니다. 또한 setOrigincopy 메모리 의미와 비슷한 것을 사용하고 있지만 그 의도를 명백하게하는 속성 정의를 공유하지 않았다는 사실에 미치지 않습니다.

그러나 다시 내가이 설정되어있어 일단, 난 그냥 당신이 객체가 인스턴스화 이러한 속성을 설정 참조하지만 그래서 당신이 할 수있는 readonly로 떠나 오히려하려는 origin 변화를 못하게하려는 의도였다 추정 무엇을가는 그들이 당신에게 돌연변이가 없을 것이라고 확신하십시오. 최종 결과는 전체적으로 직관적 인 클래스 세트입니다. 따라서

:

@implementation XYPoint 

- (instancetype)initWithX:(CGFloat)x y:(CGFloat)y { 
    self = [super init]; 
    if (self) { 
     _x = x; 
     _y = y; 
    } 
    return self; 
} 

@end 

마찬가지로, 나는 readonly가되도록 originRectangle의를 할 의향이 될 것

@interface XYPoint : NSObject 

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

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

@end 

.

당신이 당신의 XYPointRectangle 객체를 생성하면

@implementation Rectangle 

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

@end 

그런 다음, 당신은 속성 돌연변이하지 않을 것이라는 확신 할 수

@interface Rectangle : NSObject 

@property (nonatomic, readonly) XYPoint *origin; 

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

@end 

.

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

다른 접근 방식이 있지만 값을 설정하지 않는 설정기에 대한 접근 방식이 마음에 들지 않습니다. 그렇게 할 수는 있지만 직관적이지는 않습니다. 개발자는 속성을 설정할 때 해당 속성이 실제로 변경되기를 기대합니다.

+0

Rob, 고맙습니다. 왜 [myPoint setX : 50 andY : 50]을 추가할까요? 코드는 변경되지 않았습니까? NSLog (@ "출처 (% i, % i)", myRect.origin.x, myRect.origin.y); 같은 값을 출력하고,이 경우에는 myPoint 클래스를 변경할 수 있습니다. –

+0

'myRect.origin = myPoint;'에서'myPoint'를 실제로 사용하지 않고'XYPoint'를 인스턴스화하고'x'와'y'를 설정하는'setOrigin' 메소드를 호출합니다 (behaving 'copy' 메모리 의미론을 가진 속성과 같이 선언되지는 않았지만). 따라서'myPoint'를 변경하려는 시도는'setOrigin'이 생성 한 새로운'XYPoint'에 영향을 미치지 않습니다. 그러나 일단 사각형의'origin' getter를 호출하여이 객체에 대한 참조를 검색하면'x'와'y'가 변형되도록 허용합니다. – Rob

+0

귀하의 자세한 답변을 주셔서 감사합니다, 지금 내 마음 속에 그림이 분명하고, 나는 또한 이제 readonly 속성의 의미를 얻습니다. 그래도 한 가지 더있어, myRect.origin의 값을 변경하지 못하도록 기존 getter 메서드를 수정하는 방법을 알고 싶습니다. 몇 가지 팁을 적어주세요. 하단의 수정 된 질문을보십시오. 감사합니다 –