Objective-Pascal 클래스 선언
Objective-Pascal 클래스 선언
Objective-C 클래스(혹은 Objective-Pascal 클래스)는 Object Pascal 클래스와 매우 비슷하게 선언하는데, objcclass라는 키워드를 사용한다는 점이 달라요. 겉보기 문법은 Object Pascal 문법과 거의 같고, 몇 가지 확장이 더해진 형태랍니다.
출처: Free Pascal Reference - Objective-Pascal class declarations
본문
Objective-C 클래스를 가져다 쓰려면 external 수식어가 있어요. 이 수식어는 컴파일러에게 "이 클래스는 외부 오브젝트 파일이나 라이브러리에 실제로 구현되어 있고, 여기 정의는 가져오기(import)용"이라는 걸 알려줘요. 외부 Objective-C 클래스 정의의 예시를 볼게요.
NSView = objcclass external(NSResponder)
private
_subview : id;
public
function initWithFrame(rect : NSRect): id;
message 'initWithFrame:';
procedure addSubview(aview: NSView);
message 'addSubview:';
procedure setAutoresizingMask(mask: NSUInteger);
message 'setAutoresizingMask:';
procedure setAutoresizesSubviews(flag: LongBool);
message 'setAutoresizesSubviews:';
procedure drawRect(dirtyRect: NSRect);
message 'drawRect:';
end;
이 클래스 정의를 보면 Object Pascal 클래스 정의와 크게 다르지 않아요. 다만 message 지시어가 좀 더 눈에 띄죠. Objective-C나 Objective-Pascal의 각 메서드에는 반드시 연결된 메시지 이름이 있어야 해요.
위 예시에서는 클래스 정의에 외부 이름을 따로 지정하지 않았어요. 이러면 Pascal 식별자가 곧 Objective-C 클래스 이름으로 쓰여요. 그런데 Objective-C는 이름 규칙이 그렇게 엄격하지 않아서, Pascal 식별자 규칙을 따르지 않는 Objective-C 클래스 이름에는 별칭(alias)을 만들어 줘야 하는 경우가 생겨요.
이번에는 Pascal로 구현된 Objective-C 클래스를 정의하는 예시예요.
MyView = objcclass(NSView)
public
data : Integer;
procedure customMessage(dirtyRect: NSRect);
message 'customMessage';
procedure drawRect(dirtyRect: NSRect); override;
end;
external 키워드가 없다는 말은, 이 클래스의 메서드들이 나중에 이 소스 파일 안에서 구현되어야 한다는 뜻이에요. 일반적인 Object Pascal 클래스처럼 취급되는 거죠. 여기 override 지시어도 보이는데, Objective-C에서는 모든 메서드가 가상(virtual)이에요. Object Pascal에서는 가상 메서드를 재정의할 때 override 지시어를 써야 하는데, 이 규칙이 Objective-C 클래스에도 확장된 거예요. 덕분에 컴파일러가 정의의 정확성을 검증할 수 있어요.
클래스가 프로토콜의 메서드를 구현하는 경우(이건 다음 섹션에서 다뤄요)가 아니라면, message나 override 중 하나가 반드시 필요해요. 모든 메서드가 가상이므로, 새 메서드를 시작(혹은 재도입)하거나 기존 메서드를 재정의하는 둘 중 하나가 되는 거죠. 오직 프로토콜에 속한 메서드만 message나 override 없이 정의할 수 있어요.
Objective-C 클래스 선언은 부모 클래스를 지정할 수도 있고 생략할 수도 있어요. Object Pascal에서는 부모 없이 클래스를 선언하면 자동으로 TObject의 하위 클래스가 되는데, Objective-C에서는 그렇지 않아요. 부모를 생략하면 완전히 새로운 루트 클래스가 돼요. 다만 Objective-C에도 범용 루트 클래스 역할을 하는 NSObject가 있어서, Object Pascal의 TObject에 해당하는 존재로 보면 돼요. 다른 루트 클래스도 있긴 하지만, 일반적으로 Objective-Pascal 클래스는 NSObject에서 상속받는 걸 권장해요. 그래도 굳이 새 루트 클래스를 만들려면 NSObject 클래스 자신처럼 NSObjectProtocol을 구현해야 해요.
마지막으로, Objective-Pascal 클래스는 프로퍼티를 가질 수 있지만 이 프로퍼티는 Pascal 코드에서만 사용할 수 있어요. 현재 컴파일러는 Objective-C 쪽에서 쓸 수 있도록 프로퍼티를 내보내지는 않거든요.
더 알아보기
- 클래스가 다른 유닛에 정의된 경우를 다루는 정식 선언(Formal declaration)은 이어지는 섹션에서 확인할 수 있어요.
- 프로토콜 정의와 카테고리를 함께 보면 Objective-C 상호운용 모습이 더 명확해져요.