2009-08-26 3 views
5

이 약간의 구문은 Objective-C에서 다소 혼란 스러웠습니다.Objective-C : self.myObject를 호출 할 때와 myObject를 호출 할 때

myObject를 호출 할 때 self.myObject를 호출해야하는시기는 언제입니까?

중복되는 것처럼 보이지만 상호 교환 할 수 없습니다.

나를 계몽 해 주시겠습니까?

+0

비슷한 게시물을 찾았습니다 : http://stackoverflow.com/questions/1051543/should-i-use-self-keyword-properties-in-the-implementation – Jonah

답변

8

단지 액세스하는 경우에는 self.member을 사용할 이유가별로 없습니다. 과제를 수행하는 경우 간단한 @property (assign) 매개 변수 (예 : 보존, 복사 등) 이상의 작업을 수행하면 작성중인 코드를 저장할 수있어 좋습니다. 예 :

myObject = anotherObject; 
self.myObject = anotherObject; 

두 번째 선택합니다 (이 등 수를 유지 증가, 사본을 받고) 실제로 개체를 원하는 방식으로 할당하고 있음을 보장합니다. [self setMyObject:anotherObject]과 다르지 않습니다.

도트 표기법이 일반 배열 작업에서 x[5]이 어떻게 *(x + 5*sizeof(x))이되는 것과 비슷하게 컴파일러에서 대체되기 때문에 일반 메시지보다 도트 표기법을 사용하는 데 오버 헤드 나 추가 효율성이 없습니다.

1

동일한 클래스의 구현 내에서 속성 접근자는 거의 호출하지 말아야합니다. 클래스의 인스턴스 메소드는 내부 상태에 편리하게 액세스 할 수 있으므로 대개 직접 해당 상태에 액세스하는 것이 좋습니다.

합성 된 액세서를 사용하는 경우 합성 된 액세서를 호출하면 불필요한 오버 헤드가 추가됩니다. 접근 자들이 더 복잡한 구현을 가지고 있다면, 코드의 목적을 모호하게 할뿐입니다.

마지막으로 Objective-C를 처음 접하는 사람들은 self.property 구문과 합성 된 접근자를 사용하여 Cocoa 메모리 관리에 대한 이해를 피하려고합니다. 당신은 실제로 그것이 어떻게 작동 하는지를 알아야 할 필요가 있습니다. 그렇게하지 않으려 고 노력하는 것은 비생산적입니다.

+0

그냥 개체의 내부 상태로 바이올린 수 있기 때문에 모두 비참한 것은 당신이해야한다는 것을 의미하지는 않습니다. 그리고 메모리 관리가 어떻게 작동하는지 이해한다고해서 모든 팀이 완벽하게 수행 할 수 있다는 것을 의미하지는 않습니다. 여러 가지 방법 중 메모리 관리 책임을 복제하면 버그를 묻습니다. – Chuck

+0

나는 정중하게 의견이 맞지 않는다. 당신의 클래스가 @ synthesize'd 접근자를 많이 가지고 있다면, 아마도 저조한 디자인 일 것입니다. 평범하지 않은 접근자를 구현 한 경우 적절하게 사용하는 데주의해야합니다. 속성 접근자는 클래스의 * 외부 * 인터페이스를 만드는 데 사용하기위한 것입니다. 때로는 클래스가 내부적으로 외부 인터페이스를 사용하는 것이 합리적이지만, 종종 불필요한 (또는 비생산적 인) 경우가 있습니다. –

+0

어쨌든 접근자를 실제로 사용하려면 "self"를 사용하십시오. 문법은 무슨 일이 일어나고 있는지 모호하게하므로 어쨌든 명시 적 메시징을 사용해야합니다. 속성을 설정하는 경우 "[self setFoo : value]"는 "self.foo = value"보다 5 문자 길다. 읽기 액세스의 경우 차이가 더 적습니다. 코드를 한 번만 작성하므로 나중에 (또는 다른 사람이) 읽었을 때의 상황을 명확하게해야합니다. –

1

코어 데이터를 사용하는 경우, 필요할 때까지 일부 속성이 영구 저장소에서로드되지 않을 수 있으므로 기본적으로 항상 접근자를 사용해야합니다. (어쨌든, SQLite는 저장소를 사용하는 가정.)

당신이 코어 데이터를 사용하지 않는 경우에만 값을 읽는 이라면 단지 직접 myObject를 사용하는 것이 일반적으로 안전 해요. myObject의 값을 수정하는 경우 해당 속성의 값을 관찰하는 다른 객체가 올바르게 통지되는지 확인하기 위해 접근자를 사용해야합니다. 즉,

// Not changing the value of myObject, so no accessor needed 
[someMutableArray addObject:myObject]; 

// Changes the value, so you need to use the accessor 
self.myObject = newObject;  
[self setMyObject:newObject]; // Exactly identical to the previous line. 

일반적으로 오버 헤드는 거의 없습니다. 동일한 객체 내에서도 항상 접근자를 사용하는 것을 선호합니다. (물론 이니셜 라이저에서 사용하는 것에 대한 논쟁이 있지만, 별개의 문제입니다.)

3

으흠, Mark 또는 Cinder6에 동의 할 수는 없습니다.

글쎄, 나는 첫 번째 부분에서 동의한다. :-) self.foo-foo 메서드를 호출합니다. 일반 foofoo ivar에 액세스하고 있습니다.

대부분의 경우 항상 방법을 따라야합니다.실제 저장 공간에서 벗어나고 필요한 다른 행동에서 벗어나게 할 수 있습니다. 나중에 클래스를 하위 클래스로 분류하면 어떤 일이 일어나는지 생각해보십시오. 대부분의 경우, 사용자는 그들이 다루는 기능에 액세스하는 장소에서 자신의 공용 메소드를 호출하려고합니다.

개체 init 및 teardown 및 합성하지 않을 때 속성 접근자가 예외는 예외입니다. 객체 초기화 및 해체 중에 을 수행하지 않으면 메소드의 서브 클래스 구현을 호출하려고합니다. 이러한 메소드는 부분적으로 설정된 상태에서 객체를 처리 할 필요가 없기 때문입니다.

0

잘라 내기 및 말린 대답이 없습니다. 그러나 조숙 한 최적화가 나쁘다는 것을 기억하십시오. Mac의 Cocoa 또는 iPhone의 접근 자/속성 사용은 KVO 준수해야합니다. 핵심 데이터 및 코코아 바인딩이 자동으로 작동하려면 KVO 적합성이 필요합니다. 핵심 데이터에서는 속성을 수정할 때뿐만 아니라 액세스 할 때 KVO를 보장 할 필요가 있습니다.

속성 메모리 관리 동작을 보장하려면 접근 자/속성을 사용하는 것이 가장 좋습니다. 즉, 항상 setter 또는 도트 표기법을 사용하도록 ivar를 설정하고 따라야하는 메모리 관리 패턴에 따라 , 아이어를 가져올 때 항상 접근 자/속성을 사용합니다.

다양한 메모리 관리 패턴이 있습니다. 깨지지 않은 객체는 모두 접근 자에 의해 반환 된 객체가 현재의 자동 릴리즈 범위의 끝까지 살아남을 수 있도록합니다. 의미, 개체는 현재 autorelease 범위에서 명시 적으로 유지 및 autoreleased 중 하나입니다. Apple에서 권장하는 방법은 getter에서 명시 적으로 수행합니다.

- (id)foo {return [[foo retain] autorelease]; } 
- (void)setFoo:(id)aFoo { 
    if(! [aFoo isEqual:foo]) { 
    [foo release]; 
    foo = [aFoo retain]; 
    } 
} 

이는 합성 된 접근 자에서 따라 오는 패턴을 의미합니다. 개인적으로, 나는 세터에 autorelease를 선호 :이 새 값으로 교체하기 전에 이전 값을 autoreleasees

- (id)foo {return foo;} 
- (void)setFoo:(id)aFoo { 
    [foo autorelease]; 
    foo = [aFoo retain]; 
} 

. 이는 getter에서 유지 및 자동 리사이징과 똑같은 효과를 가지지 만 객체는 자동 회수 풀에만 한 번만 추가해야합니다. 대부분의 경우 보유 수는 1이고 자동 갱신되지 않으므로 어떤 일이 발생하더라도 아무데도 가지 않습니다. 속성이 여전히 보유하고있는 일부 코드 (예 : 대리자 콜백)에서 대체되면 해당 속성은 그 아래에서 사라지지 않습니다.

이 말의 의미는 접근 자/속성을 사용하면 코드의 다른 부분이 없어도 객체가 주변에서 벗어날 필요가있을 때 주변에 객체가있을 것이라는 확신을 얻게된다는 것입니다.

항상 접근 자/속성을 사용하는 마지막 그리고 가장 좋은 이유는 각 속성에 대해 하나의 가정을 덜한다는 것입니다. 즉, 해당 속성에 대한 기본 ivar이 있고 그 이름이 같습니다 (나는 두 가지 가정이라고 생각합니다) . 아마도 미래에 당신은 ivar을 파생 된 접근 자로 대체하려고 할 것입니다. 속성 표기법은 여전히 ​​작동합니다. 아마도 당신은 ivar의 이름을 바꾸기를 원할 것입니다; 재산은 여전히 ​​작동 할 것입니다. 다행히도 Xcode의 리팩토링은 대개 신뢰할 수 있지만 왜 귀찮게합니까?

객체 지향 프로그래밍의 요점은 클래스에 정의 된 인터페이스를 사용하는 것입니다. 클래스가 자신의 인터페이스를 무시하는 좋은 이유는 없습니다 (많은 편견적이고 합리적인 것들이 있지만). 접근자를 제외한 모든 메소드는 일반적으로 객체를 신성 불가침으로 취급하고 내부 상태를 비공개로 처리해야합니다. 모든 방법을 카테고리 또는 하위 클래스에있는 것처럼 작성하고 특정 디자인에 별도로 지시하지 않는 한 이바라기를 개인 상태로 취급하십시오. ivars에 직접 액세스 할 수있는 충분한 이유가 있지만 사례별로 결정됩니다.

+0

getter/setter 메서드는 Apple의 메서드와 동일하지 않습니다. getter는 기본적으로 "assign"속성에 사용할 것이고 setter는 "retain"속성 용입니다. 나는 그것이 대부분의 시간 동안 작동한다고 확신하지만, 당신이 당신 자신의 autorelease 풀을 사용하기 시작하면 그것이 풀릴 것이라고 생각한다. 코코아의 나머지 부분에 사용 된 규칙을 고수하는 것이 가장 좋습니다. –

관련 문제