본문 바로가기
프로그래밍 놀이터/iOS

[Objective-C] 프로토콜

by 돼지왕 왕돼지 2018. 1. 4.
반응형

 [Objective-C] 프로토콜


출처 : OS X 구조를 이해하면서 배우는 Objective-C Chap 12.

@optional, @protocol, @required, adopt, aFunctionWithView, anonymous object, conform, conformsToProtocol, formal protocol, forward declaration, informal protocol, NSObject category, NSObject 클래스 카테고리, Objective-C 프로토콜 선언, protocol, protocol overload, Protocol*, [Objective-C] 프로토콜, 간이 프로토콜, 객체 프로토콜, 비형식 프로토콜, 익명 객체, 클래스명 중복, 프로토콜, 프로토콜 개념, 프로토콜 상속, 프로토콜 적합성 확인, 프로토콜 전방 선언, 프로토콜 지정 형식 선언, 프로토콜 채용, 프로토콜을 사용한 프로그램 예제, 필수 기능과 옵션 기능 지정


Notice : 정리자(돼지왕 왕돼지)가 remind 하고 싶은 내용이나 모르는 내용 기반으로 정리하는 것이기 때문에 구체적인 내용은 책을 사서 보시기를 권장드립니다.


12.1. 프로토콜 개념


* 12.1.1. 프로토콜이란



* 12.1.2. 객체 프로토콜


-

어떤 프로토콜을 채용해서 그 메서드를 모두 구현한 클래스는 해당 프로토콜에 적합(conform)하다(또는 준거한다)라고 한다.

어떤 프로토콜에 적합한 클래스를 상속한 서브 클래스도 그 프로토콜에 적합하다.

또한 클래스가 어떤 프로토콜에 적합할 때는 그 인스턴스에 대해서도 해당 프로토콜에 적합하다고 표현할 수 있다.




12.2. Objective-C 프로토콜 선언


* 12.2.1. 프로토콜 선언


-

프로토콜 이름은 기존 클래스명과 겹쳐도 괜찮다.




* 12.2.2. 프로토콜 채용


-

프로토콜을 지정해서 클래스 인터페이스를 선언하고 있을 때 클래스가 그 프로토콜을 채용(adopt)하고 있다고 한다.



-

여러 프로토콜을 동시에 채용할 때, 프로토콜에 같은 메서드 선언이 중복해서 포함되더라도 문제가 없다.

프로토콜 S 와 T가 있고, 둘을 동시에 채용할 때, 양쪽에 모두 copy: 메서드가 있다고 해보자.

구현 부분에서 copy: 를 구현하면 이 메서드는 프로토콜 S 의 구현이자 프로토콜 T 구현도 되는 것이다.


하지만 셀렉터가 같더라도 인수나 반환값의 형이 다른, 즉 서명이 다른 메서드가 프로토콜 사이에 중복되어 있을 때는 문제가 생긴다.

하나의 클래스 내부에는 같은 셀렉터를 가진 다른 메서드를 선언할 수 없기 때문이다. ( overload 불가능 )

이런 프로토콜을 여러 개 포함하는 클래스는 정의할 수 없다.




* 12.2.3. 프로토콜 상속


-

어떤 프로토콜에 다른 메서드군을 추가해서 새로운 프로토콜을 선언할 수 있다.



-

이렇게 선언한 프로토콜은 상속한 프로토콜이 가진 메서드군과 새롭게 추가한 메서드군 모두를 다 가진다.

또한 상속할 프로토콜은 여러 개도 가능하다.




* 12.2.4. 프로토콜 지정 형식 선언


-

-(void) aFunctionWithView:(NSView<Clickable> *)view;


위와 같은 함수가 있다면, 인수가 단순한 NSView 형의 인스턴스가 아니라 카테고리 또는 상속을 사용한 프로토콜 Clickable 에 적합한 객체이어야만 하다는 것을 정적으로 보여준다.



-

코드로는 프로토콜이나 추상 클래스에 따른다는 것밖에 알 수 없는 구체적인 클래스명이 나와 있지 않은 객체를 익명 객체(anonymous object)라고 부른다.




* 12.2.5. 프로토콜 전방 선언


-

프로토콜명을 헤더 파일 속에 형식 선언으로만 사용할 거라면 전방 참조 지정이 가능하다.

이는 다음과 같이 작성한다.


@protocol Clickable;



* 12.2.6. 프로토콜 적합성 확인


-

컴파일러 지시자 @protocol() 을 사용하면 지정한 프로토콜을 표현하는 데이터를 가리키는 포인터를 얻을 수 있다.

@protocol() 이 표현하는 식의 값을 (Protocol*) 이라는 형을 가진 변수에 대입할 수도 있다.



-

객체가 어떤 프로토콜에 적합한지 어떤지 조사하려면 NSObject 에 정의된 다음 메서드를 사용할 수 있다.

이 녀석은 class method, instance method 둘 다에 존재한다.


(BOOL) conformsToProtocol: (Protocol*) aProtocol

     리시버 클래스가 aProtocol 로 지정한 프로토콜에 적합하다면 YES 를 돌려준다.




* 12.2.7. 필수 기능과 옵션 기능 지정


-

프로토콜 선언 속에서 컴파일러 지시자 @optional 또는 @required 를 사용하면 그 이후에 선언한 메서드는 옵션 또는 필수 메서드가 된다.

@optional 과 @required 는 순서에 상관없이 여러 번 나와도 괜찮다.

이런 지정이 없는 메서드는 @required 가 지정된 것처럼 반드시 구현해야 한다.




* 12.2.8. 프로토콜을 사용한 프로그램 예제




12.3. 비형식 프로토콜

* 12.3.1. 비형식 프로토콜이란


-

메서드군을 선언하기 위해 NSObject 카테고리로 선언하는 방법이 있다.

이것을 비형식 프로토콜(informal protocol) 또는 간이 프로토콜이라고 부른다.

비형식 프로토콜과 구별하기 위해 앞서 설명한 프로토콜을 형식 프로토콜(formal protocol) 또는 정식 프로토콜이라고 부른다.



-

비형식 프로토콜은 카테고리 선언만으로 구현이 되지 않는다.

실제로 카테고리로 선언한 메서드에는 구현이 따르지 않더라도 컴파일되고 실행되어 버린다.

하지만 메시지 송신은 실행 에러를 일으킨다.



-

비형식 프로토콜로 선언된 메서드군을 이용하고자 하는 클래스는 그 메서드를 인터페이스에서 다시 선언하고(필수는 아니다.)

구현 부분에 정의를 작성한다.

하지만 그 카테고리의 모든 메서드를 구현해야 하는 건 아니다.



-

비형식 프로토콜은 루트 클래스 카테고리일 뿐이므로 형식 프로토콜을 사용할 때처럼 컴파일할 때 형식을 확인하거나 실행할 때 프로토콜에 적합한지 확인할 수 없다.

비형식 프로토콜에 따라 메서드가 구현되었는지 조사하려면 각각의 메서드에 대해 respondsToSelector: 를 사용해 볼 수밖에 없다.



-

정리하면..

     비형식 프로토콜은 NSObject 클래스 카테고리로 선언된다.

     비형식 프로토콜로 선언된 메서드 구현은 필수가 아니다.

     컴파일할 때 비형식 프로토콜의 적합 여부를 확인하는 방법이 없다.

     실행할 때 비형식 프로토콜의 적합 여부를 확인하는 방법이 없다. 각각의 메서드를 구현했는지 확인해야 한다.




* 12.3.2. 비형식 프로토콜의 용도


-

Cocoa 환경에서 비형식 프로토콜을 사용하는 상당수의 경우가 시스템(프레임워크) 쪽에서 사용자 프로그램 쪽의 객체를 호출해서 정보를 주고받는 경우이다.



-

비형식 프로토콜은 카테고리 메서드를 실제로 정의할 때와 달리 NSObject 에 실질적으로 무언가를 더하는 건 아니다.

카테고리 선언을 임포트한 소스 파일 안에서 메서드 프로토타입 선언으로 작용한다.



-

전에는 메서드군에 있는 모든 것이 필요한 게 아니라면 보통 비형식 프로토콜로 선언했었다.

Objective-C 2.0 에서는 옵션 딸린 프로토콜을 사용할 수 있게 되어 다양한 부분에서 프로토콜을 사용한 프로그래밍 스타일이 도입되었다.





반응형

댓글