[Objective-C] 추상 클래스와 클래스 클러스터
출처 : OS X 구조를 이해하면서 배우는 Objective-C Chap 11.
Notice : 정리자(돼지왕 왕돼지)가 remind 하고 싶은 내용이나 모르는 내용 기반으로 정리하는 것이기 때문에 구체적인 내용은 책을 사서 보시기를 권장드립니다.
11.1. 추상 클래스
* 11.1.1. 추상 클래스란
-
Objective-C 에는 인스턴스를 생성할 수 있는 일반 클래스와 추상 클래스를 구별해서 정의하는 특별한 언어적 구조가 없다.
Objective-C 에서 추상 클래스라는 용어는 개념적으로만 존재한다.
-
다른 객체지향 언어는 virtual, abstract 등의 키워드를 사용해서 추상 클래스를 나타내는 수단이 있다.
Objective-C 에서는 추상 클래스로 사용하려고 만든 클래스라도 alloc 메서드를 적용하면 인스턴스가 생성된다.
* 11.1.2. 추상 클래스 예제
11.2. 클래스 클러스터
* 11.2.1. 클래스 클러스터 개념
-
클래스 클러스터(class cluster)는 같은 인터페이스를 갖고 있어 같은 기능을 제공하는 여러 클래스의 집합체이다.
인터페이스를 나타내는 추상 클래스만 공개하며,
이 인터페이스만 정의한 클래스를 클러스터의 공개 클래스(public class)라고 부른다.
공개 클래스라 불리는 추상 클래스를 구현한 구체적인 클래스는 내부에 은폐된다.
이 구체적인 클래스들은 직접 이용하면 안 된다.
이 구체적 클래스들은 보통 공개 클래스의 서브 클래스로 구현되며 비공개 서브 클래스로 불리기도 한다.
-
프로그램을 작성할 때는 공개 클래스를 일반 클래스와 똑같이 다룬다.
하지만 실제로 메모리에 존재하는, 생성된 인스턴스는 클래스 클러스터 내부에 은폐된 어떤 클래스의 인스턴스이다.
하지만 기능에는 차이가 없으므로 프로그래머는 그 차이를 거의 인식하지 못한다.
-
어떤 클래스를 구현할 때 구현 방법은 다양하다.
어떤 상황에서는 최적인 구현 방법이 다른 상황이 되면 구현 비용이 높아지기도 한다.
클래스 클러스터는 종류가 몇 가지 미리 준비된 클래스 중에서 그 상황에 가장 잘 맞는 구현을 가진 클래스가 자동으로 선택되는 구조이다.
-
다음의 것들이 클래스 클러스터로 제공된다.
NSArray, NSMutableArray
NSCharacterSet, NSMutableCharacterSet
NSData, NSMutableData
NSDate
NSDictionary, NSMutableDictionary
NSScanner
NSSet, NSMutableSet
NSString, NSMutableString
NSAttributedString, NSMutableAttributedString
NSValue, NSNumber
NSNotification
NSPipe
* 11.2.2. 실험 프로그램
-
Mac OS X 10.7 에서 다음을 실행하면 다음과 같은 결과가 나온다.
-(void)printClass(NSString *obj){
NSLog(@“Class=%@“, [NSStringFromClass([obj class]) UTF8String]);
}
int main(void){
NSString* ss = @“string”;
[self printClass:ss]; // Class_NSCFConstantString
[self printClass:[ss stringByAppendingString:@“^ ^”]]; // Class_NSCFString
[self printClass:[NSString stringWithUTF8String:”-_-“]]; // Class_NSCFString
[self printClass:NSHomeDirectory()]; // NSPathStore
}
위의 결과는 Mac OS X 버전에 따라 달라질 수 있다.
모두 같은 NSString 이라고 생각하며 프로그램을 작성해도 내부에서 다른 클래스가 사용된다.
* 11.2.3. 프로그래밍 시 주의사항
-
Objective-C 에는 클래스 클러스터를 구성하는 기능이 없다.
하지만 보통 공개 클래스는 추상 클래스이고, 구체적인 클래스는 공개 클래스의 비공개 서브 클래스로 구현된다.
클래스 클러스터를 사용하는 쪽은 일반 클래스를 사용할 때와 차이를 특별히 의식하지 않아도 된다.
하지만 다음 두 경우는 주의해야 한다.
1. 인스턴스가 속한 클래스를 조사할 때
클래스 클러스터에서 각 인스턴스는 비공개 서브 클래스의 인스턴스이다.
공개 클래스를 인수로 메서드 isMemberOfClass: 를 사용하더라도 어떤 결과가 돌아올지는 알 수 없다.
isKindOfClass: 를 사용하던가, 특정 메서드에 대응하고 있는지 어떤지를 메서드 respondsToSelector: 로 조사하는 방법이 유효하다.
2. 서브 클래스를 작성할 때
공개 클래스를 직접 상속하는 서브 클래스를 작성하더라도 기대한 것과 같은 처리는 할 수 없다.
11.3. 클래스 클러스터의 서브 클래스 만들기
-
클래스 클러스터로 제공하는 클래스의 서브 클래스를 만들려고 하면 손이 많이 간다.
그리고 클래스 클러스터는 현재로선 Foundation 프레임워크의 기본적인 클래스에만 구현되어 있고 보통은 서브 클래스를 작성할 필요가 없다.
* 11.3.1. 카테고리 대응
* 11.3.2. 원시 메서드 재정의
-
각각의 클래스 클러스터는 구체적인 데이터 구조나 알고리즘에 기초해서 정의된 원시 메서드(primitive method)라고 하는 소수의 메서드로 구현되고, 그 외의 메서드는 모두 원시 메서드를 활용해서 구현된다.
즉 클래스 클러스터 내부에서도 절차의 추상화라는 정보 은폐가 발생한다.
-
클래스 클러스터의 새로운 서브 클래스를 작성하려면 비공개 데이터 구조와 거기에 접근하는 원시 메서드를 정의하면 된다.
-
각 클래스 클러스터에서 무엇이 원시 메서드인가는 레퍼런스에 나와 있다.
또한 원시 메서드 이외에 독자적으로 구현해야 할 메서드에 대한 설명도 적혀 있다.
( 각 클러스터의 원시함수는 책 327 ~ 328p 참조 )
-
클래스 클러스터의 서브 클래스를 작성하는 방법이다.
1. 비공개 데이터 구조 정하기
인스턴스 변수의 데이터 구조를 정한다.
슈퍼 클래스인 클래스 클러스터에 있는 데이터 구조는 절대로 사용하면 안 된다.
2. 초기자 정의
init 으로 시작하는 초기자를 정의한다.
init 이외의 슈퍼 클래스 초기자를 상속해서 사용하면 안 된다.
비공개 데이터 구조가 없으면 기본 init 을 사용하면 되므로 초기자를 정의할 필요가 없다.
3. 편의 생성자 정의
필요하다면 데이터 형식명으로 시작하는 임시 객체를 생성하는 클래스 메서드를 정의한다.
4. 원시 메서드 정의 (* key!! )
자신만의 원시 메서드를 정의한다.
5. 기타 메서드 정의
원시 메서드를 정의하면 공개 클래스에서 선언한 메서드는 일단 동작하지만 그 데이터 구조의 특징을 잘 살리면 좀 더 효율적으로 구현할 수 있는 메서드가 있는데, 그런 메서드는 재정의할 수 있다.
또한 그 서브 클래스에서 독자적으로 추가할 기능이 있다면 대응하는 메서드도 정의해둔다.
* 11.3.3. 문자열의 서브 클래스 만들기
다음 글 : [Objective-C] 프로토콜
'프로그래밍 놀이터 > iOS' 카테고리의 다른 글
[Objective-C] 객체 복사와 저장 (0) | 2018.01.05 |
---|---|
[Objective-C] 프로토콜 (0) | 2018.01.04 |
[Objective-C] 카테고리 (0) | 2018.01.02 |
[Objective-C] Foundation 프레임워크의 중요 클래스 - NSDictionary, NSValue, NSNumber, NSURL (0) | 2018.01.01 |
[Objective-C] Foundation 프레임워크의 중요 클래스 - NSData, NSArray, NSSet (0) | 2017.12.31 |
댓글