Language/Objective-C

Class / Protocol / Category for Objective-C

아르비스 2011. 1. 20. 16:19

클래스

 

클래스는 항상 NSObject로부터 상속을 받아야 한다. ( 객체 생성, 정리 등 모든 관리에 필요한 기능들이 NSObject에 정의가 되어 있다. )

 

헤더파일은 .h , 구현파일은 .m 이다.

 

클래스 인터페이스 정의(.h)

 

#import <필요한헤더파일>

 

@interface ClassName : NSObject 

{

int member;   // 멤버변수들;

}

 

@property (retain) int member;

 

+ 클래스메서드;

- 인스턴스메서드;

@end

 

멤버변수들은 괄호 안에 선언을 해주며, getter, setter 메시지를 자동으로 생성해주기 위해서는 @property 에 정의를 해주어야 한다. ( @property에 정의해준 항목은 .m 파일에서 @syntyesize 하고 짝을 이루도록 해줘야 한다. )

 

클래스메서드는 앞에 + 를 표시해주며, 클래스객체 메시지를 뜻한다. 예를 들어서 NSObject의 alloc 메시지가 여기에 해당한다.

 

인스턴스메서드는 일반적인 객체의 메시지를 뜻한다.

 

클래스 구현(.m)

 

@implementation ClassName

 

@synthesize member;

 

메서드들 구현;

@end

 

@implementation과 @end 사이에 .h에서 정의한 메시지들을 구현한다.

.h에서 @property로 정의한 것을 @synthesize로 받아준다. 이렇게 하면 컴파일 시에 해당 멤버변수에 대한 getter와 setter 메시지를 자동으로 생성시켜 준다.

 

.h에서 정의하지 않은 메시지도 이 사이에서 구현할 수도 있는데, 이렇게 하면 해당 메시지는 다른 클래스에서 해당 .h 파일을 import 해서는 메시지가 존재하는지 알수 없으므로, private 메시지라고 한다. 하지만, 해당 객체를 생성한 후 private 메시지를 던지면 동작을 한다.

 

---------------------------------------------------------------

 

프로토콜

 

자바의 인터페이스, C++의 추상클래스 개념에 해당하는 것이 Objective-C의 프로토콜 개념이다. 즉, 프로토콜에는 메시지들이 정의 되어 있고, 이 프로토콜을 사용하는 클래스에서는 해당 메시지들을 모두 구현해 주어야 하는 것이다.

Objective-C에서는 클래스의 다중상속을 지원하지 않지만, 이러한 프로토콜은 한 클래스에서 여러개를 쓸수가 있다.

이런 프로토콜은 실질적으로 델리게이트 개념에 활용이 된다.

객체에서 다른객체로 메시지를 전달하는 방법은 델리게이션, 타겟-액션, 노티피케이션 이렇게 세가지 방식이 사용되는데, Xcode에게 이 객체는 어떤 델리게이트를 지원한다.. 라는 것을 알려주는 역할을 한다. ( 타겟-액션은 함수포인터를 활용한 메시지 전달이며, 노티피케이션은 어플리케이션의 경계를 넘나들수 있는 메시지 전달방식이다. 프로그램 수행중에 전화가 오던지, 아이폰을 회전시킨다던지 할때에 대한 처리 이런 노티피케이션 모니터링을 통해 수행한다. )

 

프로토콜 정의

 

@protocol ProtocolName

- 메시지들;

@end

 

프로토콜 사용

 

@interface ClassName : SuperClass <ProtocolName,ProtocolName2>

...

@end

 

여러개의 프로토콜을 사용할 때는 , 로 구분을 해준다.

그리고, 프로토콜에 정의되어 있는 메시지들은 반드시 모두 정의를 해주어야 한다.

여기서 ClassName은 ProtocolName과 ProtocolName2를 따른다고 표현을 한다.

 

프로토콜의 상속

 

@protocol ProtocolName <ParentProtocolName>

- 메시지들;

@end

 

이렇게 프로토콜을 상속받아서 새로운 프로토콜 선언도 가능하다.(다중상속도 가능)

 

그리고, 특정 객체가 어떤 프로토콜을 따른다는 것을 명시적으로 선언해주어서 컴파일러에게 알려줄 수가 있다.

 

id <ProtocolName> obj;

 

즉, obj란 객체는 id 타입인데, ProtocolName 이란 프로토콜을 따른다는 것을 명시적으로 표현을 해 준 것이다.

이런식의 표현이 가능하게 됨으로 인해, 프로그래밍 시에 구체적인 클래스의 구현에 의존하지 않고 지정한 프로토콜만을 따르는지만 신경쓰면 되는 특이한 방식의 프로그래밍을 가능하게 해준다.

굉장히 유연하다고 볼수 있으며 때에 따라서는 굉장히 유용할 거 같은 방식이다. ( obj 객체같이 구체적으로 클래스명이 명시되지 않고, 프로토콜만 명시된 객체를 anonymous object라고 한다. )

 

---------------------------------------------------------------

 

카테고리

 

자바나 C++에서는 볼수 없는 기능으로써, 보통 클래스를 확장하려면 클래스를 상속받아서 해야 하는데, 카테고리를 사용하면, 그 클래스를 그대로 쓰면서 메시지만을 추가할 수 있게 된다.

 

카테고리 정의 ( 보통 .h 파일에서 클래스와 같이 정의를 하거나 ClassName+카테고리명.h 파일에 정의를 한다.)

 

@interface ClassName (카테고리명)

추가할메시지들;

@end

 

카테고리 구현 ( 구현파일 : ClassName+카테고리명.m  )

 

@implementation ClassName (카테고리명)

메시지구현

@end

 

이렇게, 카테고리가 쓰이게 되면 프로그램 전체에서 클래스의 확장이 일어나게 된다.

협업을 할 때도 활용이 가능하다. 기본 클래스를 구현한 후 개발자별로 카테고리로 나눠서 작업을 하는 식으로 한다.

그리고, 정의, 구현 파일의 명명규칙도 클래스명+카테고리명.h / 클래스명+카테고리명.m 으로 규칙을 지켜주어 가독성을 높여야 한다.