0. 들어가기 전에


Objective-C 공부를 위하여 기본적으로 "프로그래밍 오브젝티브 C 2.0 Programing"(스티브 코찬)을 텍스트로 하였다.

프로그래밍 오브젝티브 C 2.0 Programming in Objective C 2.0
국내도서
저자 : 스티븐 코찬(Stephen Kochan) / 박세현역
출판 : 인사이트 2009.09.08
상세보기

책의 내용은 C에서 사용되는 기본 내용도 포함하고 있어 C/C++ 에 익숙한 사람에게는 지루할 수 있으나 기초부터 접근하는 사람에게는 좋은 책으로 보여집니다.


본 블로그에 내용은 위 책의 목차를 기본으로 진행하며, 추가적으로 공부해야 할 부분이나 짧게 설명된 부분들은 웹이나 다른 도서를 참고하여 진행했습니다.


1. Objective-C 역사

- 1980년대 초 브래드 콕스(Brad J. Cox)와 톰 러브(Tom Love)가 Objective-C 언어 설계.

- C 언어위에 계층적(layered)으로 올려진 구조로 객체를 사용할 수 있도록 함(Small Talk로부터 아이디어 얻음).

- 초기 모델은 OOPC(Object-Oriented Pre-Compiler)라 불리우는 C언어 기반의 Smalltalk 프리컴파일러 형태였다.

- Cox와 Love는 PPI를 설립하고 OOPC를 사용함(이후 StepStone으로 이름을 바꿈)

- 1988년 스티브 잡스가 창업한 NeXT Software가 StepStone으로부터 라이센스 받아 NEXTSTEP 개발환경, 라이브러리 개발

- 1992년 GNU 개발 환경에 Objective-C 지원 추가, GPL(General Public License)로 배포

- 1994년 NeXT Computer 와 썬마이크로시스템즈가 OPENSTEP 발표

- FSF(Free Software Foundation) 에서는 GNUStep으로 배포, Linux 버전은 LinuxStep으로 불림

- 1996년 Apple이 NeXT Software를 인수하고 OS X 의 근간으로 사용

- 2007년 Objective-C 2.0 으로 업데이트 함.


본 내용에서는 언어의 기본 용법과 일반적으로 사용되는 Foundation Framework 에서의 사용법을 알아 볼 것이다.


2. Syntax

- C의 Thin Layer 이며 Superset으로 볼 수 있다.

- C Program 도 Objective-C Compiler에서 컴파일 가능

- Objective-C Class에 C code 도 추가 가능

- Object는 Smalltalk의 문법을 따르며 그외의 문법(variables, pre-processing, expressions, function declarations and function call)은 C를 따른다.

- 객체지향 형태는 Smalltalk-style messaging 방식으로 구현 되었다.


3. Messages

- Objective-C는 객체 instance간의 message passing 방식으로 동작한다.

- 메소드를 콜(call a method)하는 것이 아니라 메세지를 보내는(send a message) 방식이다.

- Simula-style 은 컴파일 타임에 method name 이 결정되지만 Smalltalk-style 에서는 runtime 시에 결정된다.


obj->method(argument);    // in C++

[obj method:argument];    // in Objective-C


Simula-Style 

장점: 다중 상속을 허용하며 컴파일 타임 바인딩으로 빠른 실행을 보장한다.

단점: 기본적으로 동적 바인딩을 지원하지 않아 추상화 되어 있음에도 모든 메소드는 구현과 일치한다.


Smalltalk-Style(Message passing style)

장점: 아직 구현되지 않은 메소드에 메세지를 보낼수 있다.(run-time 에결정)       

        컴파일 타임에 object는 정의되지 않아도 error가 발생하지 않는다.

        

4. Interface and Implementations


- class의 선언부는 interface 로 header file (.h) 에 선언한다.

@interface ClassName: SuperClassName {

   // instance variable

}

+ classMethod;

- (return-type)classMethod2:(param1_type)paramName1 Param2CallName:(param2_type)param2_name;

@end

....


[obj classMethod2:param1 Param2CallName:param2];

- (+) 는 class methods를 나타낸다. (static method in C++)

- (-) 는 instance methods를 나타낸다. (public method in C++)


위의 코드를 C++에서 표현하면 다음과 같다.

class ClassName: public SuperClassName {

protected:

//instance variable

public:

static void* classMethod();

static return-type classMethod2(param1_type paramName1param2_type param2_name=default);

}


- class의 구현부는 implementation 로 method file (.m) 에 선언한다.

@implementation ClassName

+(return-type)classMethod {

// implementation

}

-(return-type)instanceMethod {

// implementation

}

@end


5. 인스턴스화(Instantiation)

Objective-C 에서는 할당(allocation)과 초기화(initiation) 두단계를 거쳐야 비로소 인스턴스화가 된다. 

MyObject *o = [[MyObject alloc] init];        // 두 단계를 거쳐 초기화 진행

MyObject *o = [[MyObject alloc] initWithString: myString];     // init 은 paramater를 받는 방식으로 변경 가능

MyObject *o = [MyObject new];         // 초기화 까지 진행하지만 추천하지 않는다.


init함수는 일반적으로 다음과 같이 구성된다.

-(id) init {

self = [super init];

if(self) {

// perform initialization of object here

}

return self;

}


6. Protocol

Objective-C 가 소개되었을때 다중 상속(multiple inheritance)가 표준에 들어 있었지만 구현되지 못하고 protocol 을 만들었다.

Java나 C# 의 "interface" 와 같은 기능으로 informal protocol 과 formal protocol 이 있다.

informal protocol: 클래스가 구현하거나 하지 않아도 되는 메소드의 리스트다.

formal protocol: 클래스가 반드시 구현해야 하는 메소드 리스트로 컴파일러에의해 강제된다. 즉, 구현하지 않으면 에러가 발생.


@ protocol NSLocking

- (void) lock;

- (void) unlock;

@end


@ interface NSLock : NSObject <NSLocking>

// ....

@end


7. Forwarding

- Objective-C는 메세지를 보낸다고(sending) 한다. 

- 메세지에 대한 응답도 전달(Forwarding)한다고 한다. 

- 메세지 전달은 Observer Pattern 이나 Proxy Pattern 과 같은 Design Pattern 으로 구현 될 수 있다.

- Objective-C에서는 객체를 위해 다음과 같은 한쌍의 메소드를 제공한다.

  • Forwarding Methods

- (retval_t)forward:(SEL)sel args:(arglist_t)args; // with GCC

- (id)forward:(SEL)sel args:(marg_list)args; // with NeXT/Apple systems

  • Action Methods

- (retval_t)performv:(SEL)sel args:(arglist_t)args; // with GCC

- (id)performv:(SEL)sel args:(marg_list)args; // with NeXT/Apple systems

- OpenStep, Cocoa, and GNUstep은 Object class를 사용하지 않는다. NSObjective에서는 

 - (void)forwardInvocation:(NSInvocation*)anInvocation 을 사용하여 forwarding 한다.


다음 예제를 보고 개념을 이해하자. (OpenStep으로 테스트 결과 동작하지 않았다.)

Forwarder.h

# import <objc/Object.h>

 
@interface Forwarder : Object {
 id recipient; //The object we want to forward the message to.
}
 
//Accessor methods.
- (id)recipient;
- (id)setRecipient:(id)_recipient;
  

@end


Forwarder.m

# import "Forwarder.h"

 
@implementation Forwarder
 
- (retval_t)forward:(SEL)sel args:(arglist_t) args {
 /*
 * Check whether the recipient actually responds to the message.
 * This may or may not be desirable, for example, if a recipient
 * in turn does not respond to the message, it might do forwarding
 * itself.
 */
 if([recipient respondsToSelector:sel]) {
 return [recipient performv:sel args:args];
 } else {
 return [self error:"Recipient does not respond"];
 }
}
 
- (id)setRecipient:(id)_recipient {
 [recipient autorelease];
 recipient = [_recipient retain];
 return self;
}
 
- (id) recipient {
 return recipient;
}
@end


Recipient.h

# import <objc/Object.h>

 
// A simple Recipient object.
@interface Recipient : Object
- (id)hello;
@end


Recipient.m

# import "Recipient.h"

 
@implementation Recipient
 
- (id)hello {
 printf("Recipient says hello!\n");
 
 return self;
}
 
@end


main.m

# import "Forwarder.h"
# import "Recipient.h"
 
int main(void) {
 Forwarder *forwarder = [Forwarder new];
 Recipient *recipient = [Recipient new];
 
 [forwarder setRecipient:recipient]; //Set the recipient.
 /*
 * Observe forwarder does not respond to a hello message! It will
 * be forwarded. All unrecognized methods will be forwarded to
 * the recipient
 * (if the recipient responds to them, as written in the Forwarder)
 */
 [forwarder hello];
 
 [recipient release];
 [forwarder release];
 
 return 0

}


iOS의 동작 방법은 Apple의 developer page를 참조하자.

(https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/ObjCRuntimeGuide/Articles/ocrtForwarding.html)


8. Category

- Objective-C 설계시 부터 유지보수성이 주요 관심사 였다.

- 이를 위해 Smalltalk 의 categories 개념을 가져와 확장하였다.

- 클래스의 소스나 재 컴파일 없이 기존 클래스에 category 만 추가해서 새로운 함수를 추가 할 수 있다.

- 기존 클래스의 method signature(리턴, 파라메터가 완전히)가 같은 함수를 정의 할 수도 있으며, 이때 category의 함수가 사용되어 진다.

다음 예제는 Integer 클래스에 새 카테고리로 Arithemtic 으로 정의하고 두개의 함수를 추가한 내용이다.

# import "Integer.h"
 
@interface Integer (Arithmetic)
- (id) add: (Integer *) addend;
- (id) sub: (Integer *) subtrahend; 

@end


실행파일은 다음과 같이 정의 된다.

# import "Arithmetic.h"
 
@implementation Integer (Arithmetic)
- (id) add: (Integer *) addend {
 return [self integer: [self integer] + [addend integer]];
}
 
- (id) sub: (Integer *) subtrahend {
 return [self integer: [self integer] - [subtrahend integer]];

@end


Objective-C의 전체적인 특성을 알아보았다.

다음부터는 각각의 내용들을 자세히 알아보자


본 내용은 Wiki의 Objectivce-C 페이지를 참조하였습니다.( http://en.wikipedia.org/wiki/Objective-C )

Posted by 빨간 양말