2011-04-28 2 views
13

나는이 주제에 대해 많은 게시물을 조사했다. 어쩌면 나는 "그 하나"를 가로 지르지 않았고, 누군가 그 방향으로 나를 가리킬 것이다. 질문은 간단하고 아마 간단한 대답을 가지고있을 것입니다.클래스 인스턴스 외부에서 보이지 않거나 사용할 수없는 인스턴스 변수 및 메서드를 선언하는 방법은 무엇입니까?

"public_ivar"및 "private_ivar"와 같은 두 개의 ivars가있는 경우/public을 공개하고 비공개를 헤더를 보는 사람에게 공개하지 않도록/how를 선언해야합니다. 파일?

"public_method"및 "private_method"의 경우와 같은 질문입니다.

나는 다른 사람들이보고 싶어하는 메서드와 ivars 만 공개하는 깨끗한 헤더 파일을 (다른 언어로) 좋아합니다. 당신은 당신의 헤더 파일을 공개 할 수 있어야하고, 누군가가 그들이하기로되어 있지 않은 것에 접근 할 위험에 처하지 않아야합니다. 객관적으로 C에서 어떻게합니까?

예를 들어,이 정보에 대한 액세스가 필요한 다양한 클래스 메소드 사이에서 일부 데이터, 카운터 또는 이와 유사한 정보를 추적하기 위해 ivar을 사용해야한다고 결정했다고 가정 해 봅시다. 만약 그 아이어가 @interface의 헤더에서 통상적으로 선언된다면 그것의 존재는 공개적으로 알려지며 클래스의 인스턴스를 만드는 사람은 누구나 사용할 수 있습니다. 이상적인 시나리오는이 ivar이 클래스 구현 외부에서 전혀 보이지 않는다는 것입니다.

답변

17

클래스 확장에서 인스턴스 변수 또는 선언 된 속성을 선언 할 수 있습니다. 클래스 확장은 구현 파일 (즉, 헤더 파일이 아님)에서 선언되므로 헤더 파일을 검사하는 사용자에게는 보이지 않습니다. 예를 들어, 헤더 파일 :

@interface SomeClass : NSObject 
@end 

및 구현 파일에

:/개인 클래스 확장 인스턴스 변수에 대한 액세스를 방지 아무것도 없다는 것을

@interface SomeClass() 
@property (nonatomic, assign) int privateInt; 
@end 

@implementation SomeClass 

@synthesize privateInt; 
… 
@end 

또는

@interface SomeClass() { 
    int privateInt; 
} 
@end 

@implementation SomeClass 
… 
@end 

주 (또는 클래스 확장에서 선언 된 속성에 대한 접근 자 메서드). Does a private @property create an @private instance variable?

편집 : 클래스 확장에 인스턴스 변수가 WWDC 2010 세션에서 발표되었다 (144)

편집 : 내가 스택 오버플로에 대한 다른 질문에 대한 답변으로 이것에 대해 비교적 상세한 게시물을 작성했습니다 "Clang/LLVM 2.0 컴파일러를 사용하면 클래스 확장에서 속성 및 인스턴스 변수를 선언 할 수도 있습니다."

http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/ObjectiveC/Chapters/ocCategories.html#//apple_ref/doc/uid/TP30001163-CH20-SW1

+0

좋아요, 이것 좀보세요. 나는 유전 알고리즘과 뉴럴 네트워크 (Neural Networks)를 연구 중이다. 클래스는 내부적으로 필요한 변수 더미로 끝납니다. 헤더 파일 수준에서 가시성을 필요로하는 것은 거의 없습니다. iOS4 +에 대한 구현 파일의 첫 번째 예가 (@property 문 앞에 int privateInt를 선언하지 않았으므로)? –

+0

@Martin iOS에서 Backing 인스턴스 변수의 자동 생성을 허용하는 Objective-C 2.0을 사용할 수 있는지 확실하지 않습니다. –

+0

@Martin [이 웹 페이지는 Apple 웹 사이트] (http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/ObjCRuntimeGuide/Articles/ocrtVersionsPlatforms.html%23//apple_ref/doc/uid/ TP40008048-CH106-SW1)은 특정 iOS 버전을 나열하지 않습니다. –

2

@private을 사용하여 ivars가 비공개임을 지정할 수 있습니다. 그러나 메소드를 비공개로 만들 수있는 방법은 없습니다. 메서드가 헤더 파일에 나열되지 않은 경우에도 누군가가 이름과 인수를 알고 있으면 호출 할 수 있습니다.

+0

@private는 @property 선언 (setter 및 getters)이있는 경우 실제로 아무 것도하지 않습니다. 나는 ivar 또는 private 멤버 함수가 헤더에 있기를 원하지 않는다. 아무도 그들에 대해 안다는 가정하에, 그들은 보이지 않는 채로 있어야합니다. (단지 정직한 사람들을 정직하게 유지하려는 것입니다. 파기를 원하면 무엇이라도 발견 할 수 있습니다.) 난 그냥 응용 프로그램의 다른 부분에 전혀 관련이 헤더의 모든 것들을 가지고 "더러운"이라고 생각합니다. –

+1

@Martin : 속성은 ivar이 아닙니다. 머리말에 ivars를 숨기는 방법에 대해서는 두 가지 옵션을 생각해 볼 수 있습니다. 하나의 ivar 만 다른 곳에서 선언 된 구조체에 대한 포인터로 만들거나 모든 인스턴스를 실제로 개인 서브 클래스로 만들 수 있습니다 (Apple이 수행하는 행에 따라). 클래스 클러스터 포함). – Anomie

+0

언어로 게으르다는 죄책감. @property는 기본 setter 및 getter 코드를 생성한다는 것을 이해합니다. 다른 일을합니까? –

4

사용 class extensions는 구현 파일에 클래스에 추가 할 수 있습니다. 클래스 확장은 기본적으로 몇 가지 보너스가있는 이름없는 카테고리입니다. 선언 된 속성은 합성 될 수 있고 그 안에 선언 된 모든 것이 기본 구현에 있어야하므로 컴파일러는 구현을 놓치지 않았는지 확인할 수 있습니다. 구현하기 전에 클래스 확장을 배치해야합니다. 클래스 확장에서 직접 인스턴스 변수를 추가 할 수는 없지만 속성을 추가 할 수는 있습니다.해당 인스턴스 변수가없는 속성에 대한 접근자를 합성하면 새 런타임 (os x 10.5 이상 및 모든 iOS 버전)이 인스턴스 변수를 자동으로 생성합니다. 즉, 헤더에 인스턴스 변수를 넣지 않는 한 직접 액세서를 만들 수 없습니다. private 메소드는 제한없이 클래스 확장에 추가 할 수 있지만 Anomie가 지적했듯이 클래스 덤프를 사용하면 무엇이 호출되는지를 아는 경우이를 사용하는 것이 기술적으로 가능합니다. 아무 것도 안전하지 않습니다. 클래스 확장의

사용 예제 :

@interface MyClass() 
@property (retain) id privateIvar; 
@property (readwrite) id readonlyProperty; // bonus! class extensions can be used to make a property that is publicly readonly and privately readwrite 
- (void)privateMethod; 
@end 
@implementation MyClass 
@synthesize privateIvar; // the runtime will create the actual ivar, and we just access it through the property 
- (void)privateMethod { 
    ... 
} 
... 

헤더에 이르렀 또는 속성을 사용하지 않고 "인스턴스 변수"를 만드는 또 다른 방법은 런타임에 개체에 데이터를 추가 associative references을 사용하는 것입니다. 이들은 기술적으로 인스턴스 변수와 같지 않으며 구문이 더 복잡합니다. 또한 새로운 런타임이 필요하기 때문에 실제로 사용하려는 두 가지 이유가 있습니다.이 질문의 범위를 벗어나는 범주에 인스턴스 변수를 추가하거나 이 실제로 필요하면이 필요합니다. 은밀한. 연관 참조는 컴파일 된 코드에서 메소드를 만들거나 클래스 정의에 추가하지 않으므로 래퍼를 만들지 않으면 데이터를 추가 한 후에 객체에 대해 묻지 않고 해당 메소드에 대해 알아낼 수 없습니다. 전체 사용 예제는 링크 된 페이지 하단을 참조하십시오.

+0

그래서 ... ivar에 대한 사용자 정의 된 setter 또는 getter가 "숨겨진"방식으로이 방법으로 작성해야한다면 헤더에 ivar을 노출시키지 않고? –

+0

@Martin : Bavarious가 말했듯이, 주석에서 논의 된 것처럼, ivars는 이제 클래스 확장에서 지원되므로 헤더 대신에 ivars를 선언 할 수 있습니다. 또한 연관 참조를 사용하고 주변에 래퍼를 접근 자로 작성할 수 있습니다. – ughoavgfhw

관련 문제