[[include(í‹€:작성중)]] [[TableOfContents]] ''오브ì 티브 씨''ë¼ê³ ì½ìœ¼ë©´ ëœë‹¤. ì• ì¹ì€ ''옵씨''. 브래드 콕스(Brad Cox)와 톰 러브(Tom Love)ê°€ ë§Œë“ , '''20ì„¸ê¸°ì˜ ê±¸ìž‘ 언어 Jr.'''ë¼ê³ ìƒê°í•˜ë©´ ë‹¹ì‹ ì€ ë©‹ìŸì´. 안시(ANSI) [[C]]ì— ê°ì²´ì§€í–¥ ì¸µì„ ì–¹ì–´ 만들었다. ë”°ë¼ì„œ 실행 ì‹œ 반드시 런타임(libobjc.dylib ë˜ëŠ” objc.dll)ì˜ ë„ì›€ì„ ë°›ì•„ì•¼ ìž‘ë™ ê°€ëŠ¥í•˜ë‹¤. ê·¸ë ‡ë‹¤ê³ J 모 언어처럼 ê°€ìƒ ê¸°ê³„(VM) 위ì—ì„œ ëŒì•„가는 ê±´ ì•„ë‹ˆê³ , ê°ì²´ ê°„ì˜ í†µì‹ ì„ ë‹´ë‹¹í•˜ëŠ” ìž‘ì€ ë¼ì´ë¸ŒëŸ¬ë¦¬ì— ë§í¬ë˜ì–´ì•¼ 한다. ë¬¼ë¡ ì´ ëŸ°íƒ€ìž„ ë¼ì´ë¸ŒëŸ¬ë¦¬ëŠ” [http://opensource.apple.com/source/objc4/ ì• í”Œ 오픈 소스 사ì´íŠ¸]ì— ê³µê°œë¼ìžˆìœ¼ë¯€ë¡œ '''ëŠ¥ë ¥ì´ ìžˆë‹¤ë©´''' ì–¼ë§ˆë“ ì§€ ì •ì ë¼ì´ë¸ŒëŸ¬ë¦¬ë¡œ 만들어 ë¶™ì—¬ë²„ë ¤ë„ ëœë‹¤. == ì—사 == ì´ˆê¸°ì˜ ì˜µì”¨ëŠ” Cì—ì„œ [[wiki:"OOP" ê°ì²´ì§€í–¥]]ì„ ì§€ì›í•˜ë„ë¡ ë¬¸ë²•ì„ í™•ìž¥í•œ, ì¼ì¢…ì˜ ë¬¸ë²•ì 편ì˜ì‚¬í•(syntactic sugar)으로 구현ë다. 옵씨 컴파ì¼ëŸ¬ëŠ” 옵씨 코드를 ì½ì–´ C 코드를 ë±‰ì—ˆê³ , C 컴파ì¼ëŸ¬ê°€ 그걸 ë°”ì´ë„ˆë¦¬ë¡œ 어셈블했다. 하지만 넥스트(NeXT Inc.)ê°€ 옵씨를 집어삼킨 ì´í›„, 옵씨 코드ì—ì„œ 바로 ë°”ì´ë„ˆë¦¬ë¡œ ì§í–‰í•˜ëŠ” 컴파ì¼ëŸ¬ê°€ 나왔다. ì´ë¥¼ 위해, ì˜ˆì „ì—는 GCC를 ì´ìš©í–ˆì§€ë§Œ ìš”ì¦˜ì€ ì• í”Œ 주ë„ì˜ [[LLVM/Clang]]ì„ ì´ìš©í•´ 컴파ì¼í•œë‹¤. ë¬¼ë¡ ì˜¤í”ˆ 소스 LLVM/Clang 3와 Apple LLVM/Clang 4 ëª¨ë‘ ì˜µì”¨ 코드를 컴파ì¼í• 수 있지만, 닫힌 ê°€ì§€ì¸ Apple LLVM/Clang 4ê°€ 훨씬 월등한 어셈블 ëŠ¥ë ¥ì„ ë³´ì—¬ì¤€ë‹¤ê³ . ì• ì´ˆì— ë²„ì „ë¶€í„° ì°¨ì´ë‚˜ë‹ˆê¹Œ. 여담으로 [[FreeBSD]] 재단ì—ì„œ 오픈 소스 LLVM/Clang 3를 ë‹¤ë£¨ë˜ ì‚¬ëžŒì´ [http://bsdtalk.blogspot.kr/2013/11/bsdtalk233-from-gcc-to-llvmclang-with.html ë§í•˜ê¸¸], ì°¸ê³ ì‚¼ì•„ [[GCC]] 4.2ì˜ ì˜µì”¨ 담당 부분 소스 코드를 봤다가 ê¸°ì ˆí• ë»”í–ˆë‹¤ê³ . ë¬´ë ¤ ì¼ë§Œ ì¤„ì´ ë„˜ì–´ê°€ëŠ” '''단ì¼''' C íŒŒì¼ í•˜ë‚˜ë¡œ ì˜µì”¨ì˜ ëª¨ë“ ê±¸ 처리했단다. ì´ GCC í™•ìž¥ì— ëŒ€í•´ì„œëŠ” 여러 루머가 있는ë°, 가장 ìœ ëª…í•œ 걸 ê³ ë ¤í•œë‹¤ë©´ 잡스가 빡ì³ì„œ ì—¿ë¨¹ì–´ë¼ í•˜ëŠ” 수준으로 GCCì— ë˜¥ì„ ë˜ì§„ 듯. == 문법 == [[C]] 소스 코드는 곧 옵씨 소스 코드ì´ë‹¤. ì•žì„œ ë§í–ˆë“¯, 옵씨는 Cì— í™•ìž¥ì„ ì–‡ê²Œ 바른 ì–¸ì–´ì— ê°€ê¹ë‹¤. 하지만 ê·¸ë ‡ë‹¤ê³ ì˜µì”¨ 소스 코드가 곧 C 소스 ì½”ë“œì¸ ê±´ 아니다. ì´ ë‹¨ì—서는 ì˜µì”¨ë§Œì˜ ê³ ìœ í•œ 문법과 ê¸°í˜¸ì— ëŒ€í•´ 설명하며, ì´í›„ ëª¨ë“ ì„¤ëª…ì—서는 ARC ì‚¬ìš©ì„ ê¸°ë³¸ì 으로 ê°€ì •í•œë‹¤. === ì„ ì–¸ë¶€ === ì´ ë‹¨ì—ì„œ 소개하는 ë‚´ìš©ì€ ì£¼ë¡œ í—¤ë” íŒŒì¼(*.h)ì— ë“¤ì–´ê°„ë‹¤. ==== í´ëž˜ìŠ¤ ì„ ì–¸ ==== í´ëž˜ìŠ¤ ì„ ì–¸ì€ ì™¸ë¶€ë¡œ 노출 가능한 í´ëž˜ìŠ¤ 명세를 ì˜ë¯¸í•œë‹¤. 즉, ì™¸ë¶€ì˜ í”„ë¡œê·¸ëž˜ë¨¸ë“¤ì—게 'ì´ í´ëž˜ìŠ¤ëŠ” ì´ëŸ¬ì´ëŸ¬í•œ ê¸°ëŠ¥ì„ ê°€ì§€ê³ ìžˆë‹¤'ê³ ì•Œë¦¬ëŠ” 목ì ì´ë‹¤. í´ëž˜ìŠ¤ ì„ ì–¸ì— ì“°ì´ëŠ” 옵씨 ê³ ìœ ì˜ ë¬¸ë²•ì€ {{{@interface}}} ëª…ë ¹ê³¼ {{{@end}}} ëª…ë ¹ì´ë‹¤. {{{@interface}}} ëª…ë ¹ì€ ì„ ì–¸í•˜ëŠ” í´ëž˜ìŠ¤ì˜ ì´ë¦„ê³¼ ìƒì†í•˜ëŠ” 부모 í´ëž˜ìŠ¤ ì´ë¦„, ê·¸ë¦¬ê³ ì‰¼í‘œë¡œ êµ¬ë¶„ëœ ì¤€ìˆ˜í• í”„ë¡œí† ì½œ ì´ë¦„ì˜ ëª©ë¡ì„ ì¸ìžë¡œ 받는다. 형ì‹ì€ 다ìŒê³¼ 같다: {{{ @interface í´ëž˜ìŠ¤ ì´ë¦„ : 부모 í´ëž˜ìŠ¤ ì´ë¦„ <ì¤€ìˆ˜í• í”„ë¡œí† ì½œ ì´ë¦„ 목ë¡> }}} 여기서 부모 í´ëž˜ìŠ¤ ì´ë¦„ê³¼ ì¤€ìˆ˜í• í”„ë¡œí† ì½œ ì´ë¦„ 목ë¡ì€ ì„ íƒì ì´ë‹¤. 즉, ì–´ë– í•œ í´ëž˜ìŠ¤ë„ ìƒì†í•˜ì§€ ì•Šì•„ ê·¸ ìžì‹ ì´ ìµœìƒìœ„ 뿌리(root) í´ëž˜ìŠ¤ê°€ ë ìˆ˜ë„ ìžˆê³ ì–´ë– í•œ í”„ë¡œí† ì½œë„ ì¤€ìˆ˜í•˜ì§€ ì•Šì„ ìˆ˜ 있다. {{{@end}}} ëª…ë ¹ì€ {{{@interface}}} ëª…ë ¹ì˜ ì˜ì—ì„ ë‹«ëŠ”ë‹¤. ì•„ëž˜ì— ëª‡ 가지 ì˜ˆì œê°€ 있다: {{{ // 뿌리 í´ëž˜ìŠ¤ @interface ParentClass1 @end // 뿌리 í´ëž˜ìŠ¤ë¥¼ ìƒì†í•œ í´ëž˜ìŠ¤ @interface ChildClass1: ParentClass1 @end // ë˜ ë‹¤ë¥¸ 뿌리 í´ëž˜ìŠ¤ì´ë©´ì„œ ë™ì‹œì— Protocol1ì„ ì¤€ìˆ˜ @interface ParentClass2 <Protocol1> @end // ë˜ ë‹¤ë¥¸ 뿌리 í´ëž˜ìŠ¤ë¥¼ ìƒì†í•˜ë©´ì„œ ë™ì‹œì— Protocol2와 Protocol3를 준수 @interface ChildClass2: ParentClass2 <Protocol2, Protocol3> @end }}} ==== 메서드 ì„ ì–¸ ==== 메서드 ì„ ì–¸ ì—ì‹œ ì„ ì–¸ì˜ ì¼ë¶€ì´ë¯€ë¡œ í´ëž˜ìŠ¤ ì„ ì–¸ ì•ˆì— ë“¤ì–´ê°„ë‹¤. 메서드 ì„ ì–¸ë¬¸ì˜ í˜•ì‹ì€ 다ìŒê³¼ 같다: {{{ // í´ëž˜ìŠ¤ 메서드 ì„ ì–¸ë¬¸ + (반환형) 메서드 ì´ë¦„ ; // ì¸ìŠ¤í„´ìŠ¤ 메서드 ì„ ì–¸ë¬¸ - (반환형) 메서드 ì´ë¦„ ; }}} ì„ ì–¸ë¬¸ì—ì„œ `(반환형)` ë¶€ë¶„ì€ ìƒëžµ 가능하다. ìƒëžµí•˜ë©´ 기본 ë°˜í™˜í˜•ì¸ `id`ê°€ 사용ëœë‹¤. 메서드 ì´ë¦„ ë¶€ë¶„ì€ ë‹¤ìŒê³¼ ê°™ì€ í˜•ì‹ì„ 가진다: {{{ // ì¸ìžë¥¼ 받지 않는 경우. 메서드ì´ë¦„ // ì¸ìžë¥¼ 하나 받는 경우. // ì´ ê²½ìš°, 메서드 ì´ë¦„ì€ '메서드ì´ë¦„ê³¼ì¸ìž:'ê°€ ëœë‹¤. 메서드ì´ë¦„ê³¼ì¸ìž:(ì¸ìží˜•)ì¸ìžì´ë¦„ // ì¸ìžë¥¼ ë‘ ê°œ 받는 경우. // ì´ ê²½ìš°, 메서드 ì´ë¦„ì€ '메서드ì´ë¦„ê³¼ì¸ìž1:ì¸ìž2:'ê°€ ëœë‹¤. 메서드ì´ë¦„ê³¼ì¸ìž1:(ì¸ìží˜•)ì¸ìžì´ë¦„1 ì¸ìž2:(ì¸ìží˜•)ì¸ìžì´ë¦„2 // ì¸ìžë¥¼ 세 ê°œ 받는 경우. // ì´ ê²½ìš°, 메서드 ì´ë¦„ì€ '메서드ì´ë¦„ê³¼ì¸ìž1:ì¸ìž2:ì¸ìž3:'ì´ ëœë‹¤. 메서드ì´ë¦„ê³¼ì¸ìž1:(ì¸ìží˜•)ì¸ìžì´ë¦„1 ì¸ìž2:(ì¸ìží˜•)ì¸ìžì´ë¦„2 ì¸ìž3:(ì¸ìží˜•)ì¸ìžì´ë¦„3 // ì´ ì •ë„ë©´ ì´í•´í–ˆê² 지. }}} 시범삼아 메서드 몇 개를 ì„ ì–¸í•´ë³´ê² ë‹¤: {{{ // í´ëž˜ìŠ¤ 메서드. ë°˜í™˜í˜•ì€ char *. // 메서드 ì´ë¦„ì€ 'iTakeNoParameter'. +(char *)iTakeNoParameter; // í´ëž˜ìŠ¤ 메서드. ë°˜í™˜í˜•ì€ id. // 메서드 ì´ë¦„ì€ 'allocWithZone:'. // í•˜ë‚˜ì˜ ì¸ìžë¥¼ 받으며, ê·¸ í˜•ì€ NSZone *, ì´ë¦„ì€ aZone. +allocWithZone:(NSZone *)aZone; +(id)allocWithZone:(NSZone *)aZone; // ê°™ì€ í‘œí˜„ // ì¸ìŠ¤í„´ìŠ¤ 메서드. ë°˜í™˜í˜•ì€ NSInteger. // 메서드 ì´ë¦„ì€ 'numberOfCharacter:inString:'. // ì¸ìžëŠ” ë‘ ê°œë¥¼ 받는다. 첫번째는 unicharí˜•ì˜ ch, ë‘번째는 NSString *í˜•ì˜ str. -(NSInteger)numberOfCharacter:(unichar)ch inString:(NSString *)str; // ì¸ìŠ¤í„´ìŠ¤ 메서드. ë°˜í™˜í˜•ì€ ì—†ìŒ. // 메서드 ì´ë¦„ì€ 'drawRectangleOfWidth:height:upperLeftX:upperLeftY:'. // ì¸ìžëŠ” 네 개를 받는다. ëª¨ë“ ì¸ìžëŠ” CGFloat형ì´ê³ ê·¸ ì´ë¦„ì€ ê°ê° w, h, x, yì´ë‹¤. -(void)drawRectangleOfWidth:(CGFloat)w height:(CGFloat)h upperLeftX:(CGFloat)x upperLeftY:(CGFloat)y; }}} ì½œë¡ ì—ì‹œ 메서드 ì´ë¦„ì˜ ì¼ë¶€ìž„ì„ ìœ ì˜í•˜ìž. 옵씨는 메서드 ì˜¤ë²„ë¡œë”©ì„ ì§€ì›í•˜ì§€ 않는다. ë”°ë¼ì„œ ì¤‘ë³µëœ ì´ë¦„ì˜ ë©”ì„œë“œë¥¼ ì„ ì–¸í•˜ë©´ ì»´íŒŒì¼ ì˜¤ë¥˜ê°€ ë°œìƒí•œë‹¤. ë˜í•œ, í´ëž˜ìŠ¤ ì„ ì–¸ì— ë™ë´‰ëœ ëª¨ë“ ë©”ì„œë“œëŠ” 공개(public) ê°€ì‹œì„±ì„ ê°–ëŠ”ë‹¤. 비공개(private) 메서드는 추후 ì„¤ëª…í•˜ê² ë‹¤. ==== ì¸ìŠ¤í„´ìŠ¤ 변수 ì„ ì–¸: ì œ1부 ==== ì¸ìŠ¤í„´ìŠ¤ 변수는 ë‘ ê³³ì— ì„ ì–¸í• ìˆ˜ 있다. 첫번째는 {{{@interface}}} ëª…ë ¹ 바로 다ìŒì´ë‹¤: {{{ @interface ExampleClass: ExampleSuperClass <ExampleProtocol> { // ì¸ìŠ¤í„´ìŠ¤ 변수 ì„ ì–¸ 시작 int exampleInteger; // struct를 만들 때처럼 변수를 ì„ ì–¸í•´ì£¼ë©´ ëœë‹¤. char exampleCharacter; NSString *exampleString; // 기타 ì¸ìŠ¤í„´ìŠ¤ 변수를 ì„ ì–¸í•œë‹¤. } // ì¸ìŠ¤í„´ìŠ¤ 변수 ì„ ì–¸ ë // 메서드 ì„ ì–¸ë¶€ @end }}} 추가ì 으로, ([[C++]]처럼) {{{@private}}}, {{{@protected}}}, {{{@public}}} ëª…ë ¹ì„ ì‚¬ìš©í•´ì„œ ì¸ìŠ¤í„´ìŠ¤ ë³€ìˆ˜ì˜ ê°€ì‹œì„±ì„ ì¡°ì ˆí• ìˆ˜ 있다: {{{ @interface ExampleClass: ExampleSuperClass <ExampleProtocol> { double iAmProtectedByDefault; // 기본 ê°€ì‹œì„±ì€ @protectedì´ë‹¤. @private int privateInteger; // @private 변수는 ì´ í´ëž˜ìŠ¤ 소ì†ì˜ 메서드ì—서만 ì ‘ê·¼ 가능하다. char privateCharacter; @protected // ì´ë ‡ê²Œ 다른 가시성 ëª…ë ¹ì„ ë§Œë‚˜ê¸° ì „ê¹Œì§€ëŠ” ì´ì „ 가시성 ëª…ë ¹ì´ ê³„ì† ì ìš©ëœë‹¤. int protectedInteger; // @protected 변수는 ì´ í´ëž˜ìŠ¤ì™€ ìƒì†ë°›ì€ 하위 í´ëž˜ìŠ¤ 소ì†ì˜ 메서드ì—서만 ì ‘ê·¼ 가능하다. char protectedCharacter; @public int publicInteger; // @public 변수는 개나 소나 다 ì ‘ê·¼ 가능하다. char publicCharacter; @private int privateInteger2; @public char publicCharacter2; @protected float protectedFloat; int iAmProtectedToo; } // 메서드 ì„ ì–¸ë¶€ @end }}} 가시성 ëª…ë ¹ì€ ì–´ë””ê¹Œì§€ë‚˜ ì„ íƒì ì´ë‹¤. 명시ì ì¸ ê°€ì‹œì„± ëª…ë ¹ì´ ì—†ìœ¼ë©´ ì¸ìŠ¤í„´ìŠ¤ 변수ì—는 기본ì 으로 {{{@protected}}}ê°€ ì ìš©ëœë‹¤. 하지만 옵씨 ê³ ìˆ˜ë“¤ì€ ê°€ì‹œì„±ì„ ì œí•œí•˜ë”ë¼ë„ 쓸ë°ì—†ì´ 내부 구조를 ì™¸ë¶€ì— ë…¸ì¶œì‹œí‚¨ë‹¤ëŠ” ë¬¸ì œ ë•Œë¬¸ì— {{{@interface}}} ë‚´ë¶€ì— ì¸ìŠ¤í„´ìŠ¤ 변수 ì„ ì–¸ì„ ë„£ëŠ” ê²ƒì— ë°˜ëŒ€í•˜ëŠ” 입장ì´ë‹¤. ë”°ë¼ì„œ ì´ë ‡ê²Œ í• ìˆ˜ë„ ìžˆë‹¤ëŠ” 것만 ì•Œê³ ë‹¤ìŒìœ¼ë¡œ 넘어가ë„ë¡ í•˜ìž. 다른 ë°©ë²•ì€ í´ëž˜ìŠ¤ ì •ì˜ ë¶€ë¶„ì—ì„œ 알아볼 것ì´ë‹¤. ==== 프로í¼í‹° ì„ ì–¸: ì œ1부 ==== ì¢…ëž˜ì˜ [[ìžë°”]]나 C++ ë“±ì˜ ì–¸ì–´ì—서는 í´ëž˜ìŠ¤ 외부ì—ì„œ 보호ëœ(protected ë˜ëŠ” private) ì¸ìŠ¤í„´ìŠ¤ 변수를 ë‹¤ë£¨ë ¤ë©´ 'ì ‘ê·¼ìž(accessor ë˜ëŠ” getter)'와 '변경ìž(mutator ë˜ëŠ” setter)'ë¼ëŠ” 메서드를 통해야만 한다. (friend ê°œë…ì€ ì¼ë‹¨ ì œì™¸í•˜ìž.) ë¬¼ë¡ ì˜µì”¨ë„ ì˜ˆì™¸ëŠ” 아니ë¼ì„œ, ëª¨ë“ ì¸ìŠ¤í„´ìŠ¤ 변수를 {{{@public}}}으로 놓는 미친 ì§“ì„ í•˜ëŠ” 게 아니ë¼ë©´ ì ‘ê·¼ìžì™€ 변경ìžë¥¼ ì¨ì•¼ 한다. 하지만 ë¬¸ì œëŠ” ì–¸ì œë‚˜ '''귀차니즘'''. ì–¸ì œë‚˜ {{{-(int)getInt { return anInteger; }}}}나 {{{-(void)setInt:(int)newInt { anInteger = newInt; }}}} ê°™ì€ ì¤‘ë³µ 코드를 작성하는 ê±´ ê·€ì°®ê³ ë”°ë¶„í•œ ì¼ì´ ì•„ë‹ ìˆ˜ 없다. 그래서 옵씨 2.0부터 ìƒˆë¡œì´ ë„ìž…ëœ ê°œë…ì´ ë°”ë¡œ '프로í¼í‹°(property)'. {{{@property}}} ëª…ë ¹ì„ ì‚¬ìš©í•˜ë©´ 1. ì¸ìžë¡œ ìš”ì²ëœ ì¸ìŠ¤í„´ìŠ¤ 변수가 ì„ ì–¸ë˜ì§€ ì•Šì•˜ì„ ê²½ìš° ì„ ì–¸. (ì´ ê²½ìš° 해당 ì¸ìŠ¤í„´ìŠ¤ ë³€ìˆ˜ì˜ ê°€ì‹œì„±ì€ ì •ì˜ë˜ì§€ 않는다. 그냥 ì—†ë‹¤ê³ ìƒê°í•˜ë¼.) 1. ì ‘ê·¼ì„± ì„¤ì •. 1. (ì¸ìŠ¤í„´ìŠ¤ 변수가 ê°ì²´ë¥¼ 담는 경우) 메모리 관리 ì •ì±… ì„¤ì •. 1. ì ‘ê·¼ìžì™€ ë³€ê²½ìž ìžë™ ì„ ì–¸ ë° ì •ì˜(구현). ë“±ì˜ ìž‘ì—…ì„ ê°„íŽ¸í•˜ê²Œ ì²˜ë¦¬í• ìˆ˜ 있다. 프로í¼í‹° ì„ ì–¸ë¬¸ì˜ êµ¬ì¡°ëŠ” 다ìŒê³¼ 같다: {{{ @property( 쉼표로 êµ¬ë¶„ëœ í”„ë¡œí¼í‹° ì„¤ì • ëª©ë¡ ) 변수형 변수ì´ë¦„ ; }}} ê·¸ë¦¬ê³ í”„ë¡œí¼í‹° ì„ ì–¸ë¬¸ì€ ë©”ì„œë“œ ì„ ì–¸ë¶€ì— ê°™ì´ ë“¤ì–´ê°„ë‹¤. 쉼표로 êµ¬ë¶„ëœ í”„ë¡œí¼í‹° ì„¤ì • 목ë¡ì—는 ë‹¤ìŒ ë‹¤ì„¯ ì¢…ë¥˜ì˜ ì„ íƒìžê°€ 들어갈 수 있다: * ì ‘ê·¼ìž ë©”ì„œë“œ ì´ë¦„ * 형ì‹: {{{getter = accessorName}}} * ì´ ì„ íƒìžê°€ 없으면 기본 ì ‘ê·¼ìž ì´ë¦„ì€ ì¸ìŠ¤í„´ìŠ¤ 변수 ì´ë¦„ê³¼ 똑같다. * 예를 들어, ì¸ìŠ¤í„´ìŠ¤ 변수 ì´ë¦„ì´ ê°ê° {{{name}}}ê³¼ {{{age}}}ì¸ ê²½ìš°, 기본 ì ‘ê·¼ìž ì´ë¦„ ì—ì‹œ {{{name}}}ê³¼ {{{age}}}ì´ë‹¤. * ë³€í˜•ìž ë©”ì„œë“œ ì´ë¦„ * 형ì‹: {{{setter = mutatorName}}} * ì´ ì„ íƒìžê°€ 없으면 기본 ë³€í˜•ìž ì´ë¦„ì€ {{{set변수ì´ë¦„}}}ì˜ í˜•íƒœê°€ ëœë‹¤. * 예를 들어, ì¸ìŠ¤í„´ìŠ¤ 변수 ì´ë¦„ì´ ê°ê° {{{name}}}ê³¼ {{{age}}}ì¼ ê²½ìš°, 기본 ë³€í˜•ìž ì´ë¦„ì€ {{{setName}}}, {{{setAge}}}ê°€ ëœë‹¤. * ì ‘ê·¼ì„± * {{{readonly}}}: ì ‘ê·¼ìžë§Œ ìžë™ìœ¼ë¡œ ìƒì„±ë˜ê³ 변형ìžëŠ” ìƒì„±ë˜ì§€ 않는다. ì´ ê²½ìš°, 아래 메모리 관리 ì •ì±…ì€ ì“¸ëª¨ê°€ 없다. * {{{readwrite}}}: ì ‘ê·¼ìžì™€ 변형ìžê°€ ìžë™ìœ¼ë¡œ ìƒì„±ëœë‹¤. * 위 ë‘ ì„ íƒìžëŠ” ìƒí˜¸ë°°íƒ€ì (mutually exclusive)으로, 반드시 둘 중 하나만 들어가야 한다. ìƒëžµí•˜ë©´ 기본ì 으로 {{{readwrite}}}ì´ë‹¤. * 메모리 관리 ì •ì±… * {{{assign}}}: 변형ìžëŠ” ì¸ìžë¡œ ë°›ì€ ê°’ì„ ì¸ìŠ¤í„´ìŠ¤ ë³€ìˆ˜ì— ë‹¨ìˆœ 대입한다. ì¸ìžë¡œ ì›ì‹œí˜•ì„ 받는 경우ì—는 반드시 ì´ ì„ íƒìžë¥¼ ì¨ì•¼ 한다. ì¸ìžë¡œ ê°ì²´ë¥¼ 받는 경우, ì´ ê°ì²´ì˜ ìƒëª…ì£¼ê¸°ì— ì „í˜€ ê°„ì„í• ìˆ˜ 없다. * {{{retain}}}, {{{strong}}}: 변형ìžì˜ ì¸ìžë¡œ ë°›ì€ ê°ì²´ì— 대해 ê°•í•œ ì†Œìœ ê¶Œì„ í–‰ì‚¬í•œë‹¤. ì›ì‹œí˜•ì—는 ì´ ì„ íƒìžë¥¼ ì ìš©í• ìˆ˜ 없다. ì´ ë³€ìˆ˜ê°€ ì–´ë– í•œ ê°ì²´ë¥¼ ë“¤ê³ ìžˆëŠ” ë™ì•ˆ 해당 ê°ì²´ëŠ” ì ˆëŒ€ 소멸ë˜ì§€ 않는다. * {{{copy}}}: 변형ìžì˜ ì¸ìžë¡œ ë°›ì€ ê°ì²´ë¥¼ ë³µì œí•˜ì—¬ 사본 ê°ì²´ë¥¼ ì¸ìŠ¤í„´ìŠ¤ ë³€ìˆ˜ì— ë„£ëŠ”ë‹¤. ì›ì‹œí˜•ì—는 ì´ ì„ íƒìžë¥¼ ì ìš©í• ìˆ˜ 없다. 사본 ê°ì²´ì— 대해서는 ê°•í•œ ì†Œìœ ê¶Œì„ í–‰ì‚¬í•œë‹¤. ì›ë³¸ ê°ì²´ì˜ ìƒëª…주기ì—는 ê°„ì„하지 않는다. * {{{weak}}}: 변형ìžì˜ ì¸ìžë¡œ ë°›ì€ ê°ì²´ì— 대해 약한 ì†Œìœ ê¶Œì„ í–‰ì‚¬í•œë‹¤. ì›ì‹œí˜•ì—는 ì´ ì„ íƒìžë¥¼ ì ìš©í• ìˆ˜ 없다. ê°ì²´ëŠ” ê°•í•œ ì†Œìœ ê¶Œì„ í–‰ì‚¬í•˜ëŠ” 주체가 없어지는 즉시 소멸ë˜ëŠ”ë°, ì´ ë•Œ 약한 ì†Œìœ ê¶Œì„ í–‰ì‚¬í•˜ëŠ” 주체는 ëª¨ë‘ {{{nil}}}ë¡œ ìž¬ì„¤ì •ëœë‹¤. * 위 세 ì„ íƒìžëŠ” ìƒí˜¸ë°°íƒ€ì (mutually exclusive)으로, 반드시 ì…‹ 중 하나만 들어가야 한다. ìƒëžµí•˜ë©´ 기본ì 으로 {{{assign}}}ì´ë‹¤. * ì›ìžì„±(atomicity) * {{{nonatomic}}}: ì ‘ê·¼ìž/변형ìžê°€ ì¸ìŠ¤í„´ìŠ¤ ë³€ìˆ˜ì— ì ‘ê·¼í• ë•Œ ìž ê¸ˆ(lock)ì„ ì‚¬ìš©í•˜ì§€ ì•Šë„ë¡ í•œë‹¤. 다중 ìŠ¤ë ˆë“œ 환경ì—ì„œ ì‚¬ìš©í• ë•ŒëŠ” 주ì˜í•˜ì—¬ì•¼ 한다. 다만, ì½ê¸° ì „ìš©(readonly) 프로í¼í‹°ì— ì 용하면 소소하게나마 성능 í–¥ìƒì„ ê¾€í• ìˆ˜ 있다. * '''주ì˜''': {{{atomic}}} ì„ íƒìžëŠ” 없다. 그냥 {{{nonatomic}}}ì„ ì“°ì§€ 않으면 ì›ìžì 으로(== lock 사용) ë™ìž‘한다. ë‹¤ìŒ ì˜ˆì œëŠ” 몇 ê°œì˜ í”„ë¡œí¼í‹°ë¥¼ ì„ ì–¸í•œë‹¤: {{{ @interface Developer: Employee <CoffeeConsumer> { @private NSInteger employeeSince; BOOL fired; } // NSString *í˜•ì˜ name. // ìƒì„±ë˜ëŠ” ì ‘ê·¼ìž: -(NSString *)name;. // ìƒì„±ë˜ëŠ” 변형ìž: ìƒì„± 안 ë¨. // ì¸ìŠ¤í„´ìŠ¤ 변수 ìžë™ ìƒì„± 여부: ìƒì„±ë¨. // ì›ìžì„±: ì›ìžì ì´ì§€ ì•ŠìŒ. @property(readonly, nonatomic) NSString *name; // NSIntegerí˜•ì˜ employeeSince. // ìƒì„±ë˜ëŠ” ì ‘ê·¼ìž: -(NSInteger)employeeSince;. // ìƒì„±ë˜ëŠ” 변형ìž: ìƒì„± 안 ë¨. // ì¸ìŠ¤í„´ìŠ¤ 변수 ìžë™ ìƒì„± 여부: ìƒì„± 안 ë¨. // ì›ìžì„±: ì›ìžì ìž„. @property(readonly) NSInteger employeeSince; // BOOLí˜•ì˜ fired. // ìƒì„±ë˜ëŠ” ì ‘ê·¼ìž: -(BOOL)isFired;. // ìƒì„±ë˜ëŠ” 변형ìž: -(void)setFired:(BOOL)fireHim;. // ì¸ìŠ¤í„´ìŠ¤ 변수 ìžë™ ìƒì„± 여부: ìƒì„± 안 ë¨. // 메모리 관리 ì •ì±…: 단순 대입. // ì›ìžì„±: ì›ìžì ì´ì§€ ì•ŠìŒ. @property(readwrite, nonatomic, getter = isFired) BOOL fired; // NSArray *í˜•ì˜ thingsToDo. // ìƒì„±ë˜ëŠ” ì ‘ê·¼ìž: -(NSArray *)thingsToDo;. // ìƒì„±ë˜ëŠ” 변형ìž: -(void)assignThingsToDo:(NSArray *)jobs;. // ì¸ìŠ¤í„´ìŠ¤ 변수 ìžë™ ìƒì„± 여부: ìƒì„±ë¨. // 메모리 관리 ì •ì±…: ë³µì œ. // ì›ìžì„±: ì›ìžì ìž„. @property(readwrite, copy, setter = assignThingsToDo) NSArray *thingsToDo; @end }}} === ì •ì˜ë¶€ === ì´ ë‹¨ì—ì„œ 소개하는 ë‚´ìš©ì€ ì£¼ë¡œ 구현 파ì¼(*.m)ì— ë“¤ì–´ê°„ë‹¤. ==== í´ëž˜ìŠ¤ ì •ì˜ ==== í´ëž˜ìŠ¤ë¥¼ ì„ ì–¸í–ˆìœ¼ë©´ ì •ì˜ë„ 해야 í• ê²ƒì´ë‹¤. 다ìŒê³¼ ê°™ì´ ì •ì˜í•œë‹¤: {{{ @interface í´ëž˜ìŠ¤ ì´ë¦„ }}} ì—시나 {{{@end}}} ëª…ë ¹ìœ¼ë¡œ {{{@implementation}}}ì˜ ì˜ì—ì„ ë‹«ëŠ”ë‹¤. {{{ @implementation EmptyClass // And then there were none. @end }}} ==== 메서드 ì •ì˜ ==== 메서드 ì •ì˜ëŠ” í´ëž˜ìŠ¤ ì •ì˜ ë‚´ë¶€ì— ë“¤ì–´ê°„ë‹¤. ì •ì˜í• 때는 ì„ ì–¸í• ë•Œì²˜ëŸ¼ 메서드 ì´ë¦„ê³¼ ì¸ìž ì „ì²´ë¥¼ ì ê³ ì„¸ë¯¸ì½œë¡ ìœ¼ë¡œ 마ê°í•˜ëŠ” ê²ƒì´ ì•„ë‹ˆë¼ ì¤‘ê´„í˜¸ë¥¼ ì—´ê³ ë‹«ì•„ 메서드 본체를 ì •ì˜í•œë‹¤. ì´í•´ë¥¼ 위해 ì˜ˆì œë¡œ ì„¤ëª…í•˜ê² ë‹¤. 윗부분 메서드 ì„ ì–¸ì˜ ì˜ˆì œë¥¼ ìž¬í™œìš©í•˜ê² ë‹¤: {{{ @implementation ExampleClass +(char *)iTakeNoParameter { return "asdf"; } +(id)allocWithZone:(NSZone *)aZone { // implementation detail. } -(NSInteger)numberOfCharacter:(unichar)ch inString:(NSString *)str { NSUInteger j = [str length], k = 0; unichar *asdf = (unichar *)malloc(sizeof(unichar) * j); if(NULL == asdf) return -1; [str getCharacters:asdf range:NSRangeMake(0, j)]; for(NSUInteger i = 0; i < j; ++i) { if(ch == asdf[i]) ++k; } return k; } -(void)drawRectangleOfWidth:(CGFloat)w height:(CGFloat)h upperLeftX:(CGFloat)x upperLeftY:(CGFloat)y { // implementation may vary. } @end }}} ==== ì¸ìŠ¤í„´ìŠ¤ 변수 ì„ ì–¸: ì œ2부 ==== 아까 위ì—ì„œ ë§í–ˆë“¯, í´ëž˜ìŠ¤ ì„ ì–¸ë¶€ì— ì¸ìŠ¤í„´ìŠ¤ 변수 ì„ ì–¸ì„ ê°™ì´ ì 는 ê²ƒì€ ì“¸ë°ì—†ëŠ” ìƒì„¸ êµ¬í˜„ì„ ì™¸ë¶€ë¡œ 노출시키는 것ì´ë¼ 옵씨 ê³ ìˆ˜ë“¤ì€ ì‹«ì–´í•œë‹¤. ë”°ë¼ì„œ ì• í”Œì€ ì˜µì”¨ 2.0 ì´í›„ì˜ ì–´ë–¤ ì—…ë°ì´íŠ¸ì—ì„œ í´ëž˜ìŠ¤ êµ¬í˜„ì— ì¸ìŠ¤í„´ìŠ¤ 변수 ì„ ì–¸ì„ í• ìˆ˜ 있ë„ë¡ í—ˆìš©í–ˆë‹¤. 다ìŒê³¼ ê°™ì´ í•œë‹¤: {{{ @implementation ExampleClass { // ì¸ìŠ¤í„´ìŠ¤ 변수 ì„ ì–¸ 시작 int protected; @public char inaccessibleFromOutside; // @public 변수가 êµ¬í˜„ë¶€ì— ìˆ¨ì–´ìžˆì–´ì„œ, 외부ì—ì„œ ì ˆëŒ€ ì ‘ê·¼ì´ ë¶ˆê°€ëŠ¥í•˜ë‹¤. @protected long protectedButInaccessibleFromChilds; // @protected 변수가 êµ¬í˜„ë¶€ì— ìˆ¨ì–´ìžˆì–´ì„œ, ìƒì†í•˜ëŠ” í´ëž˜ìŠ¤ëŠ” ì ‘ê·¼í• ìˆ˜ 없다. @private unsigned long long private; } // ì¸ìŠ¤í„´ìŠ¤ 변수 ì„ ì–¸ ë @end }}} ==== 프로í¼í‹° ì„ ì–¸: ì œ2부 ==== [[include(í‹€:ProgrammingLanguage)]]