2011. 4. 15. 17:32

객체 초기화

클래스로 인스턴스를 생성한 경우, 대부분 초기값을 필요로 합니다.  초기화를 생략한 경우 제대로 동작하지 않을 수도 있습니다.

 일반적인 객체 지향 언어에서 객체를 안전하고, 확실하게 초기화하는 방법은 생성자를 이용하는 입니다.  생성자는 클래스의 인스턴스가 만들어진 직후에 자동으로 호출되는 특별한 메서드입니다. 하지만 Objective-C에서는 생성자가 존재하지 않습니다.

 대신 생성자를 루트 클래스에서  제공하는 방식을 채택하고 있기 때문에, 루트 클래스에서 제공되는 초기화를 위한 메소드를 명시적으로 호출해야 합니다.  Object 루트 클래스와 Mac OS X NSObject 클래스는 init라는 메서드가 객체의 초기화를위한 메소드로 정의되어 있습니다.  init 메소드를 이니셜라이저라고 합니다.

 

 - (id) init;

 

 일반적으로 객체를 인스턴스화 하면서 바로 init 메시지를 전송합니다.  작업은 자동이 아니라 명시적으로 메시지에서 호출해야 합니다. 일반적으로 다음과 같이 사용하고 있습니다.

 

 [[클래스 이름 alloc] init]

 

그러나 new 메소드를 사용하면 위에서 설명한 이니셜라이즈 작업을 자동으로 호출하게 수도 있습니다.  C++ 계열의 객체 지향 언어의 사용자라면 이런 방식이 익숙할지도 모릅니다.

 

 + (id) new;

 

 어떤 것을 사용할지는 개발자의 선택입니다.  가령, 초기화를 하지 않거나 처리할 코드가 없는 클래스에서는 new 사용하는 편이 나을지도 모릅니다.하지만 한가지 방식으로 통일하는 것이 추후에 확장을 대비해서는 좋은 방법이 것입니다.

 Object 루트 클래스를 상속받은 새로운 클래스를 선언하면, init 메소드를 재정의 하여 초기화 작업에 사용 있습니다.  인스턴스 변수의 초기값 설정과 시스템에 대한 등록 처리, 클래스가 작동하는데 필요한 사전 데이터를 로드 하는 등의 작업을 부분에서 처리하는 것이 좋습니다.  그러나, init 메소드를 재정의하는 경우 루트 클래스인 Object 클래스의 init 메소드를 호출해야 하는 것을 반드시 잊지 마십시오.

#import <stdio.h>

#import <objc/Object.h>

@interface Point : Object

{

 int x, y;

}

-   (id) init;

-   (int) getX;

-   (int) getY;

@end

@implementation Point

-   (id) init

{

 [super init];

 x = y = 0;

 printf ( "init method \ n");

 return self;

}

-   (int) getX

{

 return x;

}

-   (int) getY

{

 return y ;

}

@end

 

int main()

{

 id pt = [Point new];

 printf ( "X = %d Y = %d \n", [pt getX], [pt getY]);

 return 0;

}

  프로그램은 좌표를 나타내는 X Y 값을 제공하는 Point 클래스를 제공합니다.  Point 클래스는 Object 루트 클래스를 상속하고 init 메서드를 재정의 합니다.  따라서 new 메소드를 사용하여 인스턴스를 생성하는 경우 인스턴스를 생성한 후에 init 메소드가 자동으로 호출됩니다.

  프로그램의 init 메소드는 먼저 부모 클래스를 올바르게 초기화할 필요가 있기 때문에 super init 메시지를 보내야 합니다.  부모 클래스의 init 메소드가 실행되면,부모 클래스의 모든 기능을 완전히 이용할 있게 됩니니다.  그런 다음 인스턴스 변수 x y 0으로 초기화하고 이니셜라이저가 호출되는 것을 시각적으로 확인하기 위해, printf() 함수에서 표준 출력으로 문자열을 출력하여 확인 합니다.

 

 지정 이니셜라이즈

 init 메소드는 인스턴스가 생성된 직후에 초기화를 위해서 호출되는 초기화 메소드지만 인수를 받을 없는 단점이 있습니다.  서브 클래스에서 새롭게 추가한 멤버변수를 초기화할 경우 초기값을 인수로부터 받게 경우는 빈번히 발생하게 됩니다.  이런경우 하위 클래스에서 새로운 이니셜 라이저를 선언해야 합니다.  이와 같은 Object 루트 클래스의 새로운 init 메소드를 지정 이니셜라이저 라고 합니다.

 지정 이니셜라이저는 관습적으로 initWith 시작하는 인수를 받는 메서드입니다. 서브 클래스에서 수퍼 클래스의 지정 이니셜 라이저를 재정의하는 경우 항상 슈퍼 클래스의 지정 이니셜 라이저를 먼저 호출해야 합니다.  그렇지 않으면 문제가 발생 수도 있습니다.

 #import <stdio.h>

 #import <objc/Object.h>

 

 @interface Point : Object

 {

  int x, y;

 }

 - (id) init;

 - (id) initWithPoint : (int) x int : (int) y;

 - (int) getX;

 - (int) getY;

 @end

 

 @implementation Point

-   (id) init

 {

  [super init];

  return [self initWithPoint : 0 int : 0];

 }

-   (id) initWithPoint : (int) x int : (int) y

 {

  self -> x = x;

  self -> y = y;

  return self;

 }

 

 - (int) getX {return x;}

 - (int) getY {return y;}

 @end

 

 int main()

{

 id pt1 = Point new];

 id pt2 = [[Point alloc] initWithPoint : 400 int : 300];

 

 printf ( "pt1.X = %d, pt1.Y = %d \n", [pt1 getX] [pt1 getY]);

 printf ( "pt2.X = %d, pt2.Y = %d \n", [pt2 getX] [pt2 getY]);

 

 return 0;

}

  프로그램의 Point 클래스는 지정된 이니셜라이저인 initWithPoint 메서드를 정의합니다.  initWithPoint 자동으로 호출되는 메소드가 아니기 때문에, 명시적으로 호출 해야 합니다. 일반적으로 init 메소드를 호출하고 지정 이니셜라이저를 차례로 호출하는 형태가 가장 안정적인 디자인이 것입니다.

Posted by openserver