클래스의 선언과 정의를 바르게하고, Object 루트 클래스의 alloc 메소드를 호출하면 클래스의 인스턴스가 생성됩니다. 클래스의 정의는 구조체의 선언과 같은 것으로, 인스턴스의 생성한다는 것은 구조체 변수를 정의하고 구조를 표현하는 데 필요한 메모리를 할당 행위와 비슷합니다. 그러나 클래스는 멤버 변수와 그것을 처리하는 전용의 함수를 연결하는 점에서 구조와 크게 다릅니다.
마지막으로 클래스를 선언하고 메소드를 정의하고 그것을 호출하는 것을했다. 마지막 메소드는 인수와 반환 값을 교환하지 않는 지극히 단순한 것이었지만,이 자리에서는 더 복잡한 방법을 실현하기 위해, 메소드의 상세를 설명합니다. 특히, 메소드는 함수와 달리 설계론의 개념에서 인스턴스 나 클래스의 역할과 연결되어야합니다.
예를 들어, 2 차원 좌표의 점을 나타내는 Point 클래스를 작성한다고합니다. 이 경우, Point 클래스는 좌표 X와 Y를 제공해야합니다. Point 클래스는 int 형의 인스턴스 변수 x와 y를 선언하고이 값을 제어하는 메소드 군을 제공해야합니다.
원칙적으로 클래스의 인스턴스 변수는 클래스의 외부에서 액세스 할 수 없습니다 . 왜냐하면, 변수가 자유롭게 변경되어 버리면, 변수의 의미 나 입출력 데이터의 사양이 변경된 경우 등 보수성이나 코드 전체의 유연성이 저하되기 때문입니다. 그래서 Objective-C에서는 변수에 액세스하는 방법을 사용합니다. Point 클래스의 기본적인 선언은 다음과 같이 될 것입니다.
@interface Point : Object
{
int x, y;
}
- (void)setPoint:(int)ptx:(int)pty;
- (int)getX;
- (int)getY;
@end
이 클래스의 선언에서는 좌표를 저장하기위한 변수 x와 y를 선언하고,이 변수에 클래스의 외부에서 액세스하기위한 메소드를 선언합니다. setPoint 메소드는 x와 y의 값을 변경하는 방법에서 getX와 getY 메소드는, 각각의 변수를 얻을 수있는 방법입니다. 이 같은 방법을 특히 액세서 메소드 라고합니다. 또한, 이러한 인스턴스의 성질에 대한 외부에 제공하는 정보를, 특히 속성 이라고 부르기도합니다.
인수를 메소드는 인수 형을 () 안에 지정하고 그 다음에 가인의 이름을 지정합니다. 이 때의 ()는 캐스트 식과 마찬가지로 형식을 지정하지 않으면 반환 값과 마찬가지로 id 형식이 기본으로되어 있습니다. 복수의 인수가있는 경우, 또한 콜론 : 계속 지정합니다. 보다 구체적으로는, 메소드의 선언은 다음과 같습니다.
- (반환 값형) 메소드 명 : (인수 형) 변수 이름 라벨 : ....
여러 인자를받는 메소드는 변수 이름 뒤에 레이블을 지정할 수 있습니다. 비교적 Objective-C의 세계에서는 레이블을 지정할 수 습관이되고 있습니다 만,이 라벨과 콜론은 메소드 이름의 일부로 인식되는 것입니다.
레이블과 콜론이 이름의 일부로 인식되고 있기 때문에, Objective-C에서는 같은 반환 값, 인수, 메소드 이름을 가진 메소드를 구별하여 호출 할 수 있습니다. 예를 들어 (void) setPoint : (int) : int)라는 메소드와 (void) setPoint : (int) label : (int) 메소드는 다른 메소드로서 선언, 정의 할 수 있습니다.
인수 된 메소드를 호출 메시지 식으로 메소드 이름 뒤에 인수에 전달할 값을 지정합니다. 레이블을 지정하지 않는 전자의 setPoint의 경우 [obj setPoint : x : y]의 형태로 호출 반면, 레이블 방법은 [obj setPoint : x label : y]의 형태로 호출합니다. 인수의 수나 라벨 만 다르면, 메소드 이름이 같아도 구별하여 호출 할 수있는 구조입니다. 특정 기능을 제공하는 방법을 다양한 형태에 대응하여 제공하려는 경우 라벨이 필요합니다. setPoint 메소드를 int 형 이외의 정수에도 대응시키고 싶은 경우 등은 중요한 것입니다.
#import <stdio.h> #import <objc / Object.h> @interface Point : Object { int x, y; } - (void) setPoint : (int) ptx int : (int) pty; - (int) getX; - (int) getY; @end @implementation Point - (void) setPoint : (int) ptx int : (int) pty { x = ptx; y = pty; } - (int) getX { return x; } - (int) getY { return y; } @end int main () { id point1, point2; point1 = [Point alloc]; point2 = [Point alloc]; [point1 setPoint : 16 int : 32]; [point2 setPoint : 256 int : 128]; printf ( "point1 : X = % d, Y = % d \ n", [point1 getX, point1 getY]); printf ( "point2 : X = % d, Y = % d \ n", point2 getX, point2 getY]); return 0; }
이 프로그램의 Point 클래스는 2 개의 정수형 인수를받는 setPoint : int : 메소드와 설정되어있는 좌표를 반환 getX, getY 메소드를 선언합니다. setPoint 메소드의 선언은 setPoint (int) ptx : (int) pty에서도 문제 없습니다 만, 장래 setPoint를 확장하는 것을 생각하면 라벨을 지정해야 겠지요.
main () 메소드에서는 alloc 메소드를 사용하여 Point 클래스의 인스턴스를 두 개 생성하고 있습니다. point1 변수와 point2 변수가 가리키는 인스턴스는 다르기 때문에 각각의 인스턴스에 설정 한 값은 별도의 메모리에 저장되는 것이 출력 결과에서 확인할 수 있습니다.
메소드의 스코프 범위 내에는 가인과 선언 된 변수 이외에 암시 적 변수로 self 가 정의되어 있습니다. self 변수는 id 형식에서 항상 메소드를 호출 한 인스턴스를 참조하고 있습니다. 즉, 메소드를 실행하고있는 객체 자신을 나타내는 변수가 self입니다.
self는 메소드 이외의 장소에서는 사용하지 못하고 항상 메소드 응 실행 코드 부분에서만 암시 낮은 존재하고 있습니다. self를 이용하여 객체의 인스턴스 변수에 개체에서 참조 할 수 있습니다. 이것은 메소드의 가인의 변수 이름이 인스턴스 변수 이름을 은폐 해 버린 때 등에 사용할 수 있습니다. 액세서 메소드에서는 특히 중요한 존재가 될 것입니다.
#import <stdio.h> #import <objc / Object.h> @interface Point : Object { int x, y; } - (void) setPoint : (int) ptx int : (int) pty; - (int) getX; - (int) getY; @end @implementation Point - (void) setPoint : (int) x int : (int) y { self-> x = x; self-> y = y; } - (int) getX { return x; } - (int) getY { return y; } @end int main () { id point1, point2; point1 = [Point alloc]; point2 = [Point alloc]; [point1 setPoint : 32 int : 64]; [point2 setPoint : 256 int : 128]; printf ( "point1 : X = % d, Y = % d \ n", [point1 getX, point1 getY]); printf ( "point2 : X = % d, Y = % d \ n", point2 getX, point2 getY]); return 0; }
이 프로그램의 setPoint : int : 메소드는 가인 선언 한 이름이 인스턴스 변수 x와 y에 충돌하고 있습니다. 이것 자체는 문제가 없지만,이 메소드의 스코프 범위에서는 인스턴스 변수가 은폐되어 버립니다. 그래서 인스턴스 변수에 접근하는 수단으로 현재 메소드를 실행하는 객체를 참조하는 self 변수를 사용하고 있습니다. 클래스의 외부에서 인스턴스 변수에 참조 할 수 없지만, 메소드는 클래스의 내부이므로 개체에서 직접 인스턴스 변수에 액세스 할 수 있습니다. 프로그램은 self-> x 형태로 인스턴스 변수에 전달 된 데이터를 저장하고 있습니다.
또한 메소드에서 동일한 인스턴스가 다른 메소드를 호출하는 경우에도 self가 필요합니다. 몇 가지 방법이 기능의 일부를 공유하는 설계 등은 동일한 클래스의 다른 메서드를 호출해야 할 수 있습니다.
#import <stdio.h> #import <objc / Object.h> @interface Test : Object - (void) methodA; - (void) methodB; @end @implementation Test - (void) methodA { printf ( "method A \ n"); [self methodB]; } - (void) methodB { printf ( "method B \ n"); } @end int main () { [Test alloc] methodA]; return 0; }
이 프로그램의 Test 클래스에서는 methodA 메소드로부터 methodB 메소드를 self 오브젝트를 사용해 호출합니다. self는 methodA를 실행하는 인스턴스이므로 동일 인스턴스의 methodB를 호출하는 것입니다.