티스토리 뷰
반 객체지향(Half-of-OOP)
가장 먼저 명심하자. 오브젝티브-C는 C언어의 슈퍼셋(Super Set)이고 C++의 객체 지향과는 거리가 멀다. 오브젝티브-C 언어는 마치 객체지향 프로그래밍(OOP, Object-Oriented Programming) 처럼 보이지만 객체지향 언어가 아니다. 그렇다고 완전히 함수형 언어도 아니다.
하지만, 오브젝티브-C는 객체지향의 가장 대표적인 특징인 상속(Inheritence)이 가능하고 인터페이스 구현이 가능하다. ANSI-C 입장에서 바라보면 상속과 인터페이스 구현은 함수형 언어로서 가당치도 않은 언어적 특성임에 틀림 없을 것이다. (이 문장의 인터페이스는 오브젝티브-C의 @protocol을 의미함.)
물론, C 언어에서도 구조체(struct), 포인터(pointer) 등을 조합하여 객체처럼 다룰 수 있지만, 오브젝티브-C 처럼 상속과 인터페이스의 구현은 객체지향 언어가 아님에도 불구하고 완전히 객체지향 프로그래밍 처럼 개발하는데 모자람이 없을 지경이다.
정리해 보면 오브젝티브-C의 객체지향 특징은 다음과 같다.
1. 상속성(Inheritance)
상속성은 부모의 특징을 물려 받음과 동시에 재정의(override), 부모 호출(super 또는 base)를 지원한다. 더 자세히 말할 필요는 없을 것 같아서 걍~ 넘어간다.
// 오브젝티브-C 의 상속
@interface MFAppController : NSObject
{
// .. 생략 ..
}
2. @protocol - 인터페이스 구현
오브젝티브-C의 프로토콜(protocol)은 C#과 Java의 interface와 같지만, 한 가지 다른 점은 인터페이스에 정의된 메서드 구현이 필수가 아니라는 점이다. 프로토콜의 모든 메서드를 굳이 구현하기 싫으면 하지 않아도 오브젝티브-C는 너그럽게 용서해 준다.
어떻게 이런 것이 가능할까? 지난 아티클 ‘[Objective-C] 아름다운을 추구하는 오브젝티브-C 언어 1/N’ 에서 다룬 것 처럼 메시지를 기반으로 메서드 호출을 위임하는 언어적인 특성 때문에 가능하다. 모든 프로토콜의 메서드를 정의하든 말든 컴파일러는 컴파일 할 뿐이고, 런타임에서 메시지를 통해 메서드를 호출해서 메서드가 구현되지 않았으면 예외를 발생하던가 아니면 씹던가 하게 된다. (단, @optional과 @required 참고)
// 오브젝티브-C 프로토콜 및 다중 상속
@protocol Animal
- (void)say;
@end
@protocol Duck <Animal, NSObject>
- (void)swim;
@end
3. @category - 확장 메서드
카테고리(@category)는 C#에서의 확장 메서드(Extension Methods)와 똑같다. 확장 메서드는 2008년 C# 3.0에 언어적인 특징으로 포함되었다. 이와 더불어 람다 표현식(Lambda Expression), 이 두 가지는 C# 코드로 표현한 라인 수를 급격히 줄일 수 있었고, 더 섬세한 객체지향 프로그램에 집중할 수 있게 해준다.
@interface NSArray (ConvertableArray)
- (NSDictionary*)ConvertToDictionary;
@end
@implementation NSArray (ConvertableArray)
- (NSDictionary*)ConvertToDictionary
{
// .. 실제 구현 생략 ..
return nil;
}
@end
int main(int argc, const char * argv[])
{
@autoreleasepool {
NSArray* arr = [NSArray arrayWithObjects:@"A", @"B", nil];
NSDictionary* dic = [arr ConvertToDictionary];
// TODO
}
return 0;
}
같은 코드로 C# 으로 변환하면 다음 코드와 같다.
public static class ConvertableArray
{
public static IDictionary ConvertToDictionary(this IList list)
{
// .. 구현 생략 ..
return null;
}
}
class MainClass
{
public static void Main (string[] args)
{
var arr = new List<String> { "A", "B" };
var dic = arr.ConvertToDictionary ();
}
}
하지만, 내부적으로 처리되는 매커니즘은 완전히 틀리다. 무엇이 그렇게도 완전히 틀릴까?
- C# 확장 메서드는 정적 클래스의 정적 메서드로만 표현할 수 있다.
- 오브젝티브-C 카테고리는 인스턴스 메서드이다.
그러므로 오브젝티브-C의 카테고리(@category)는 C#의 확장 메서드와 달리 인스턴스화 된 카테고리 메서드가 호출될 때 마다 참조 카운터가 증가한다. NSArray
객체가 인스턴스화 되었기 때문에 카테고리 메서드를 호출할 수 있다는 이야기가 된다.
카테고리의 메서드는 디버거를 통해 다음과 같이 역어셈블리 된다. 역어셈블리 코드를 좀 더 보기 편하기 위해 로컬 변수를 선언하여 살펴 보았다.
먼저 48만큼 메모리 사이즈를 확보한 다음 넘어온 값과 로컬 변수를 초기화하거나 값을 대입한다. rbp-8( =rdi)
은 self
가 들어간 것이고, rbp-16 (=rsi)
는 메서드 정보가 들어간다. rbp-20 (=$10)
은 INT32 정수 값이 할당된다. 마지막으로 +48로 원래 스택 포인터로 돌아와 빈 값을 리턴하게 된다. 스택이 8씩 자라는 것은 필자가 소스코드를 64비트 대상으로 컴파일 했기 때문이다.
0x100000d40: pushq %rbp
0x100000d41: movq %rsp, %rbp
0x100000d44: subq $48, %rsp
0x100000d48: movq %rdi, -8(%rbp)
0x100000d4c: movq %rsi, -16(%rbp)
0x100000d50: movl $10, -20(%rbp)
0x100000d57: movq -8(%rbp), %rsi
0x100000d5b: movq %rsi, %rdi
0x100000d5e: callq 0x100000eac ; symbol stub for: objc_retain
0x100000d63: leaq -32(%rbp), %rdi
0x100000d67: movabsq$0, %rsi
0x100000d71: movq %rax, -32(%rbp)
0x100000d75: movl $1, -36(%rbp)
0x100000d7c: callq 0x100000eb8 ; symbol stub for: objc_storeStrong
0x100000d81: movabsq$0, %rax
0x100000d8b: addq $48, %rsp
0x100000d8f: popq %rbp
0x100000d90: ret
'C++' 카테고리의 다른 글
[퀴즈] 프로그래머를 위한 문제 #4 - 또라이 같은 C 언어 코드를 설명하라 (0) | 2013.12.30 |
---|---|
[Objective-C] OSX 매버릭스(Mavericks) 업데이트 후 개발 중인 앱이 정상 작동하지 않는다면 (0) | 2013.10.25 |
[Objective-C] 아름다움을 추구하는 오브젝티브-C 언어 1/ 2- 언어적 특성 (0) | 2013.09.11 |
[퀴즈] 프로그래머를 위한 문제 #3 - 미로 찾기 (0) | 2013.07.08 |
[퀴즈] 프로그래머를 위한 문제 #2 - 스택 프레임(Stack Frame) (1) | 2013.07.05 |
- Total
- Today
- Yesterday
- ***** MY SOCIAL *****
- [SOCIAL] 페이스북
- [SOCIAL] 팀 블로그 트위터
- .
- ***** MY OPEN SOURCE *****
- [GITHUB] POWERUMC
- .
- ***** MY PUBLISH *****
- [MSDN] e-Book 백서
- .
- ***** MY TOOLS *****
- [VSX] VSGesture for VS2005,200…
- [VSX] VSGesture for VS2010,201…
- [VSX] Comment Helper for VS200…
- [VSX] VSExplorer for VS2005,20…
- [VSX] VSCmd for VS2005,2008
- .
- ***** MY FAVORITES *****
- MSDN 포럼
- MSDN 라이브러리
- Mono Project
- STEN
- 일본 ATMARKIT
- C++ 빌더 포럼
- .
- TFS 2010
- 땡초
- .NET Framework 4.0
- Team Foundation Server
- Windows 8
- Visual Studio 2008
- 팀 파운데이션 서버
- Visual Studio 11
- LINQ
- Silverlight
- ASP.NET
- test
- c#
- TFS
- Visual Studio
- monodevelop
- Managed Extensibility Framework
- .NET
- github
- POWERUMC
- Team Foundation Server 2010
- 비주얼 스튜디오
- umc
- ALM
- 비주얼 스튜디오 2010
- mono
- testing
- 엄준일
- Visual Studio 2010
- MEF