쩨주's blog
2010년 7월 8일 목요일
2010년 4월 22일 목요일
流言蜚語
세간에 떠도는 근거 없는 소문을 유언비어(流言蜚語)라 한다. 그런 유언비어가 떠돌게 되는 원인은 두 가지로, 하나는 정치적 폭력에 의해 언로(言路)가 막혀 있을 경우이고, 다른 하나는 정당성을 공적(公的)으로 확보하지 못한 집단, 또는 개인이 자기를 드러내지 않고 상대를 공격하는 비열한 수단인 경우이다.
하지만 그 어느 편도 내용이 진술보다는 퍼뜨린 자, 또는 조직한 자의 주관과 목적에 더 충실하게 되어 있다는 점에서는 동일하다.
정의감에 의해서든, 사적(私的)인 이익을 위해서든, 또는 정치적 폭력이 두려워서이건, 자기를 드러내면 금세 그 목적이 탄로 날까 두려워서이건, 그 근원이 뚜렷하지 않은 이상 진실 여부에 대한 토론이나 비판이 불가능하기 때문이다.
쉽게 말하자면, 듣는 사람이 좀 이상하게 느껴져도 전하는 사람 또한 <들었을 뿐>이기 때문에 따져 물을 수가 없게 된다.
그러므로 슬기로운 사람은 유언비어를 들어도 전하지 않는다. 진실은 확인할 길이 없고, 꾸며댄 자나 퍼뜨린 자의 주관과 목적만 되풀이 강조되는 그런 종류의 뜬소문을 다시 전하는 것은, 잘해야 용기 없는 정의(正義)가 주관(主觀)에 뇌동(雷同)하는 것이 되고 자칫하면 악당을 쓰러뜨리기 위한 다른 악당의 계교를 도와주는 결과가 되기 때문이다.
하지만 우매한 민중들 (사람들)이 지니고 있는 자가증폭(自家增幅)의 속성은 선동력으로까지 커져 어쭙잖은 기폭제(起爆劑)로도 강력한 권력집단의 몰락을 가져오는 경우가 있기도 한 까닭이다.
이문열삼국지 중에 나오는 내용이라는데.. 요즘같이 혼란한 세상, 인터넷이 만들어 낸 쓰레기정보속에서 가끔씩 드는 생각과 너무 비슷하길래..
2010년 2월 22일 월요일
워렌 버핏이 미국의 대학생들에게..
자신의 미래 수익의 10%를 투자해야 한다면.
투자하고 싶은 사람을 주위에서 골라보십시요.
대부분은
가장 잘생긴 사람이나 운동을 잘하는 학생
키가 큰 학생, 가장 날쌘 학생
가장 돈이 많은 학생
나아가 가장 머리가 좋은 학생을 고르진 않습니다.
당신이 고르는 대상은 그들 가운데
가장 인격이 뛰어난 사람 일것입니다.
누가 가장 많은 수익을 올릴지 모든 사람은
본능적으로 알기 때문입니다.
거꾸로.
당신이 가장 투자하고 싶지 않은 사람,
다시 말해 가장 수익이 떨어질것으로 보이는 사람을 골라보십시요.
이번에도 가장 성적이 떨어지거나
운동시합이 있을때마다 후보신세를 벗어나지 못하고 만년벤치나
데우고 있는 학생이나.
나아가 지능이 가장 떨어지는 학생이 아닐 가능성이 큽니다.
당신이 고르는 대상은
잔머리를 굴리고 거짓말을 하고
남의 공로를 가로채는-
신뢰할수 없고 이기적이고 오만하며 독선적이고
신용이 없는 사람일것입니다.
이 두 부류 사람들의 차이는
인생에서 성공하느냐
실패하느냐의 차이입니다.
인격은
당신의 말,. 행동, 옷차림,
당신이 쓴 글,
심지어 당신의 생김새에서 까지..
모든면에서 들어납니다.
결코 숨길수도 위조할수도 없습니다.
숨길수 없지만..
고쳐질수 없는 것도 아니니 희망을 잃지 마십시요.
인격 또한 하나의 습관이기 때문이다.
당신이 닮고 싶은 사람의 인격의 특징을
종이 한장에다가 써보십시요.
반대로 당신이 닮고 싶지 않은
사람의 인격의 특징을 써보십시요.
그리고 둘 사이의 차이를 비교해보십시요.
그것은 결코 큰 차이가 아닐것입니다.
야구공은 100미터 넘게 던지느냐.못던지느냐의
역기를 100킬로 넘게 드느냐. 마느냐의 차이가 아닐것입니다.
거짓말을 하느냐. 안하느냐.
자기마음대로 말을 내밷느냐.
한번더 생각을 하느냐.
남을 배려하는 말투인가.
남을 무시하는 말투인가.
조금 더 신경써서 일하느냐.
조금 더 게으르게 행동하느냐..
잘못을 저질렀을때.정직한가, 아니면, 둘러대며 남탓하는가.
결코 큰차이가 아닌..이런 작은 차이가
엄청난 차이를 만들어냅니다.
여러분이 아직 젊다면..
여러분이 닮고 싶은 인격을 조금만 신경써 연습한다면.
머지 않아 당신의 인격으로 만들수 있을것입니다.
인격 또한 습관이기 때문입니다.
습관은 처음엔 깃털같아 결코 느낄수 없지만.
나중엔 무거운 쇳덩이 같아 결코 바꿀수 없습니다.
내 나이때 습관을 고치는것은 거의 불가능에 가깝습니다.
여러분은 젊습니다.
아직 충분히 기회가 있습니다.
그리고 정직하십시요.
어떠한 경우에도 거짓말하지 마세요.
변호사가 뭐라하든 신경쓰지 마세요.
그저 자기가 보는 그대로 풀어놓으십시요.
저의 성공에는
우리(버크셔해서웨이)의 평판덕이 큽니다.
저는 저의 사람들에게
법의 테두리보다 훨씬 더 안쪽의 경계선에서 행동하며.
우리에게 비판적이고 또한 영리한 기자가
우리의 행동을 신문에 대서특필할수 있을 정도로.
행동하길 바랬습니다.
저는 저의 회사들의 지사장들에게 2년에 한번 이와같은
메세지를 줍니다.
"여러분은
돈을 잃어도 상관 없습니다.
많은 돈이어도 괜찮습니다. 하지만 평판을 잃지 마십시요.
인격을 잃지는 마십시요.
우리에겐 돈을 잃은 여유는 충분히 있으나.
평판을 잃는 여유는 조금도 없습니다."
여러분 (대학생들)은 아직 젊습니다.
지금의 모습보다 훨씬 낳아질 가능성이 충분합니다.
결코 돈 때문에 직장 선택하거나
사람을 사귀지 마십시요.
여러분이 좋아하는 직업을갖고
좋아하고 존경할 만한 사람만을 사귀십시요.
저는 아무리 큰 돈을 벌어준다고 해도.
도덕적으로 믿을수 없고.
신용이 가지 않은 사람과는 함께 사업을 하지 않습니다.
그것은
언젠가는 뱉어내야한다란걸 알고 있기때문입니다.
저는 1년내내 제가 좋아하는 일을
제가 좋아하는 사람들과만 함께 합니다.
제 속을 뒤집어 놓는 사람과는 상종도 안하죠.
결국 가장 중요한것은 이것이라고 생각합니다.
이것이 제 원칙입니다.
금전적으로 성공하는것은 두번째의 일입니다.
전 가난했던..젊은 시절에도.
저는 충분히 행복했고. 지금 처럼 제 일을 사랑했습니다.
가난했던때와 조금은 부유해진 지금과 바뀐것은
저에겐 별로 없습니다.
여러분들이 좋아하는 일을 즐겁게 하고.
성실히.
그리고 정직하게 생활한다면.
거기다 유머 또한 잃지 않고 하루를 유쾌히 감사한다면..
여러분은
성공을 결코 피할수 없을 겁니다.
- 워렌 버핏 미국의 대학생들에게 -
출처- 워렌버핏, 벤자민 그레이엄 연구모임(2007년 10월 27일)
2010년 2월 8일 월요일
4. 메소드
4. 메소드
억세서 메소드
클래스의 선언과 정의를 바르게 하고, Object 루트클래스의 alloc 메소드를 호출하면 클래스의 인스턴스가 생성됩니다. 클래스의 정의는 구조체의 선언과 같은 것으로, 인스턴스를 생성하는 것은 구조체형의 변수를 정의하고 구조체를 표현하기 위하여 필요한 메모리를 할당하는 행위와 비슷합니다. 그러나 클래스는 멤버변수와 그것을 처리하는 전용함수를 연결하는 점에서 구조체와 크게 다릅니다.
전회에 클래스를 선언하고, 메소드를 정의하여 그것을 호출하는 일을 했습니다. 전회의 메소드는 인수나 반환값을 전달하지 않는 매우 단순한 것이었지만, 여기서는 보다 복잣한 메소드를 실현하기 위하여 메소드를 상세히 해설합니다. 특히, 메소드는 함수와는 달리, 설계론의 개론에서 인스턴스나 클래스의 역할에 관련되어야 합니다.
예를 들면, 2차원좌표의 점을 나타내는 Point 클래스를 작성한다고 합니다. 이 경우 Point 클래스는 좌표 X와 Y를 제공해야 합니다. Point 클래스는 int형의 인스턴스변수 x와 y를 선언하고, 이들의 값을 제어하는 메소드군을 제공해야 할 필요가 있습니다.
원칙적으로, 클래스의 인스탄스변수에는 클래스의 외부에서는 억세스할 수 없습니다. 왜냐하면, 변수가 자유롭게 변경되어 버리면 변수의 의미나 입출력하는 데이터의 사양이 변경되는 경우 등, 보수성이나 코드전체의 유연성이 저하되기 때문입니다. 그래서, Objective-C 에는 변수에 억세스하기 위하여 메소드를 사용합니다. Point 클래스의 기본적인 선언은 다음과 같이 될 것입니다.
{
int x, y;
}
- (void)setPoint:(int)ptx:(int)pty;
- (int)getX;
- (int)getY;
@end
이 클래스의 선언에는 좌표를 보존하기 위하여 변수 x와 y를 선언하고, 이 변수에 클래스 외부에서 접근하기 위한 메소드를 선언합니다. setPoint 메소드는 x와 y의 값을 변경하기 위한 메소드로 getX와 getY메소드는 각각의 변수를 가져오기 위한 메소드입니다. 이같은 메소드를 특별히 억세서메소드라고 부릅니다. 또, 이같은 인스턴스의 성질에 관련된 외붕에 제공하기 위한 정보를 특별히 프로퍼티라고도 합니다.
인수를 받아들이는 메소드는 인수형을 ()의 속에 지정하고, 그 다음에 가인수의 이름을 지정합니다. 이 때의 ()는 캐스트식과 같이 형을 지정하지 않는 경우에는 반환값과 같이 id형이 기본값이 됩니다. 복수의 인수가 있는 경우, 다시금 콜론 : 에 이어 지정합니다. 보다 구체적으로는 메소드의 선언은 다음과 같습니다.
복수의 인수를 받아들이는 메소드는 변수명의 뒤에 레이블을 지정할 수 있습니다. 비교적, Objective-C의 세계에는 레이블을 지정하는 일이 습관이 되어있습니다만, 이 레이블과 콜론은 메소드명의 일부라고 인식되어지는 것입니다.
레이블과 콜론이 이름의 일부라고 인식되어지기 때문에, Objective-C에는 같은 반환값, 인수, 메소드명을 가진 메소드를 구별하여 호출하는 일을 할수 있습니다. 예를 들어 (void)setPoint:(int):(int) 라고 하는 메소드와 (void)setPoint:(int) label:(int) 메소드는 다른 메소드로 선언, 정의할 수 있습니다.
인수가 붙은 메소드의 호출에는 메시지식에 메소드명에 이어서 인수에 넘겨주는 값을 지정합니다. 레이블을 지정하지 않은 전자의 setPoint 의 경우 [obj setPoint:x:y] 라고 하는 형으로 호출하는대 반하여, 레이블을 붙인 메소드는 [obj setPoint:x label:y] 라는 형태로 호출합니다. 인수의 수나 레이블이 다르면, 메소드명이 같아도 구별하여 호출할수 있는 구조입니다. 특정의 기능을 제공하는 메소드를 여러 가지 형에 대응하여 제공하고 싶은 경우에 레이블이 필요하게 됩니다. setPoint 메소드를 , int형 이외의 정수에도 대응시키고 싶은 경우등은 중요할 것입니다.
#import <stdio.h> @interface Point : Object @implementation Point int main() { [point1 setPoint:16 int:32]; printf("point1:X=%d, Y=%d\n", [point1 getX] , [point1 getY]);
#import <objc/Object.h>
{
int x, y;
}
- (void)setPoint:(int)ptx int:(int)pty;
- (int)getX;
- (int)getY;
@end
- (void)setPoint:(int)ptx int:(int)pty {
x = ptx;
y = pty;
}
- (int)getX {
return x;
}
- (int)getY {
return y;
}
@end
id point1 , point2;
point1 = [Point alloc];
point2 = [Point alloc];
[point2 setPoint:256 int:128];
printf("point2:X=%d, Y=%d\n", [point2 getX] , [point2 getY]);
return 0;
}
이 프로그램의 Point 클래스는 2개의 정수형인수를 받아들이는 setPoint:int: 메소드와 설정되어있는 좌표를 반환하는 getX, getY메소드를 선언하고 있습니다. setPoint 메소드의 선언은 setPoint(int)ptx:(int)pty 에도 문제없습니다만, 장래 setPoint를 확장하는 일을 생각할 경우는, 레이블을 지정하는 것이 좋을 것입니다.
main() 메소드에는 alloc 메소드를 이용하여 Ppint 클래스의 인스턴스를 2개 만듭니다. point1 변수와 point2변수가 가리키는 인스턴스는 다르기 때문에, 각각의 인스턴스에 설정된 값은 개별의 메모리에 보존되어있는 것이고, 출력결과에서 확인할 수 있습니다.
암묵의 self
메소드의 스코프범위 내에는 가인수나 선언된 변수이외에 암묵의 변수인 self과 정의되어있습니다. self 변수는 id형에 항상 메소드를 호출하는 인스턴스를 참조합니다. 즉, 메소드를 실행하는 오브젝트자신을 나타내는 변수가 self입니다.
self 는 메소드이에의 장소에서든 사용할 수 없고, 항상 메소드 실행코드부분에만 암묵적으로 존재합니다. self를 이용함에 다라, 오브젝트의 인스턴스변수에 오브젝트에서 참조하는 일이 가능합니다. 이것은, 메소드의 가인수의 변수명이 인스턴스 변수명을 은폐하고 있을 때등에 이용할 수 있습니다. 억세서메소드에는 특히 중요한 존재일 것입니다.
#import <stdio.h>
#import <objc/Object.h>
@interface Point : Object
{
int x, y;
}
- (void)setPoint:(int)ptx int:(int)pty;
- (int)getX;
- (int)getY;
@end
@implementation Point
- (void)setPoint:(int)x int:(int)y {
self->x = x;
self->y = y;
}
- (int)getX {
return x;
}
- (int)getY {
return y;
}
@end
int main() {
id point1 , point2;
point1 = [Point alloc];
point2 = [Point alloc];
[point1 setPoint:32 int:64];
[point2 setPoint:256 int:128];
printf("point1:X=%d, Y=%d\n", [point1 getX] , [point1 getY]);
printf("point2:X=%d, Y=%d\n", [point2 getX] , [point2 getY]);
return 0;
}
이 프로그램의 setPoint:int: 메소드는 가인수에 선언된 이름이 인스턴스변수 x와 y에 충돌하고 잇습니다. 이것자체는 문제가 없습니다만, 이 변수의 스코프범위에는 인스턴스변수가 은폐되어 버립니다. 그래서 인스턴스변수에 억세스하는 수단으로, 현재의 메소드를 실행하고 있는 오브젝트를 참조하는 self변수를 사용합니다. 클래스외부에서 인스턴스변수에 참조하는 일은 할수 없지만, 메소드는 클래스의 내부이므로, 오브젝트에서 직접 인스터스변수에 억세스할 수 있습니다. 프로그램에는 self->x 라는 형태로, 인스턴스 변수에 넘겨준 데이터를 보존하고 있습니다.
또, 메소드에서 같은 인스탄스의 다른 메소드를 호출하는 경우에도 self가 필요합니다. 일부 메소드가 기능의 일부를 공유하고 있는 설계등에는 동일한 클래스의 다른 메소드를 호출할 필요가 있습니다.
#import <stdio.h> @interface Test : Object @implementation Test int main() {
#import <objc/Object.h>
- (void)methodA;
- (void)methodB;
@end
- (void)methodA {
printf("method A\n");
[self methodB];
}
- (void)methodB {
printf("method B\n");
}
@end
[[Test alloc] methodA];
return 0;
}
이 프로그램의 Test클래스에는 methodA메소드에서 methodB메소드를 self 오브젝트를 사용하여 호출하고 있습니다. self는 methodA를 실행하고 있는 인스턴스이므로, 동일 인스턴스의 methodB를 호출한다는 것입니다.
2010년 1월 29일 금요일
3. 클래스의 선언과 정의
3. 클래스의 선언과 정의
컴파일러 디렉티브
Objective-C 언어는 오브젝트 지향형 언어이기 때문에, 재이용가능한 데이터와 제어를 패키지화한 템플릿을 제공하는 일을 할 수 있습니다. 이것을 일반적으로 클래스라고 부르고, 클래스는 메모리실체를 생성하기 위한 정보입니다.
클래스의 개념은 C언어의 구조체를 발전시킨 것으로, 구조체와 같은 데이터의 연관부에 추가하여, 데이터와 제어(함수)를 연관시킵니다. 그렇기 때문에 코드는 항상 데이터를 처리하는 전용의 함수를 안전히 불러내는 일을 하고 일련의 기능을 한 개의 서브시스템으로 제공하는 일이 가능한 것입니다.
클래스를 이용하는 것에는 구제체와 같이 일단 선언이 필요합니다. Objective-C 언어의 클래스의 선언은 예약어나 구문이 아닌 컴파일러 디렉티브를 이용합니다. 컴파일러 디렉티브는 컴파일러에 Objective-C로 확장되어진 클래스의 선언이나 설치등에 이용되어 @마크로 시작된다는 특징을 가집니다.
클래스를 선언하는 컴파일러 디렉티브는 @interface 로 시작하고 @end로 끝납니다. 이들 사이에 클래스에 관련되는 변수영역과 함수를 선언합니다. Objective-C의 클래스 선언과 정의의 관계는 다른 언어에 비해 복잡하므로, 처음에는 당황할지도 모르겠습니다.
{
인스탄스 변수선언
...
}
메소드선언
@end
이 시점에서 C언어계의 오브젝트지향언어와는 선언방법이 상당히 다른 것이 보입니다. 인스턴스변수와는 클래스에 관련된 변수를 말하는 것으로, 구조체의 멤버와 같은 존재입니다. 단, 구조체와는 달리 인스턴스변수에는 클래스의 외부에서 억세스하는 일은 불가능합니다. 인스턴스변수를 이용할 수 있는 것은 원칙적으로 클래스에 관련된 메소드만 가능합니다. 인스턴스변수가 존재하지 않는 경우는 인스턴스변수 선언과 {}를 생략하는 일이 가능합니다.
메소드라는 것은 클래스에 관련된 함수를 말합니다. 통상의 함수와 차이는, 메소드는 메소드를 불러내는 클래스의 실체에 연관되어져 있기 때문에 직접 인스턴스변수에 억세스 하는 일이 가능합니다.
클래스명의 직후에 부모클래스를 지정하는 일이 있습니다만, 부모클래스라는 것은 무엇일까요? 오브젝트지향은 한번 정의되어진 기능을 확장하는 계승이라고 불리는 기능을 제공하지 않으면 안됩니다. 계승관계는 생물의 진화론에 예를 들면, 개나 고양이등의 여러 가지 실체에 공통되는 추상적인 기능은 표유류클래스로 정의하고 개클래스나 고양이클래스는 포유류클래스를 계승한다는 것처럼 프로그램하는 것입니다.
부모클래스를 지정하지 않는 클래스는, 다른 클래스의 정점이 되기 때문에 루트클래스라고 불립니다. Java나 .NET에서는 , 플랫폼이 기본이 되는 루트클래스를 제공하는 구조를 채용하고, C++언어는 루트클래스를 정하지 않고 루트클래스를 개발자가 개발할 수 있게 설계합니다. Objective-C 언어는 그 중간적인 형태로, 원칙적으로는 루트클래스에서 개발하는 일을 할 수 있지만, 사실상은 컴파일러등의 처리계가 루트클래스를 제공하지 않으면 안됩니다.
루크클래스는 처리계에 따라 다릅니다만 GCC라면 Object 클래스가, Mac OS X의 Cocoa 환경이라면 NSObject 클래스가 루트클래스가 됩니다. 독자의 루트클래스를 개발할 경우라면 부모클래스를 지정하지 않습니다만, 통상적으로는 처리계가 제공하는 루트클래스를 계승합니다. 루트클래스를 개발하는 경우에 선언은 다음과 같이 할 것입니다.
{
인스턴스변수선언
...
}
메소드선언
@end
어째서, 루트클래스를 계승하지 않으면 안되는가 하는 것은 루트클래스는 클래스가 정상적으로 동작하기 위하여 필요한 기본적인 기능을 제공한다고 하는 역할이 있기 때문입니다. 루트클래스가 존재하지 않는다면, 클래스의 실체를 작성하기 위하여 번잡한 수속을 모든 클래스에 기술하지 않으면 안 됩니다. 힙메모리의 확보나 해방등의 기본적인 처리수속은 루트클래스에 맡겨두고, 개발자는 개발목적의 기능을 기술하는 일에 집중할 수 있는 것입니다.
인스턴스 변수의 선언은 통상의 변수와 같습니다만, 메소드의 선언은 함수의 선언과는 상당히 다릅니다. 이 메소드 선언의 사양은 C++에 비하여 Objective-C 나 C언어프로그래머에게 받아들여지지 않는 커다란 요인의 한 개라고 생각될 것입니다. 메소드의 선언은 다음과 같습니다.
어째서, 함수의 선어과 이정도로 다른 것인가, C언어와 하이브리드언어와의 사양상의 문제가 뚜렷이 드러나게 됩니다. 최초의 마이너스 기호 - 는 이 메소드가 클래스의 실체인 오브젝트에 관련된 것을 보여줍니다. 통상의 메소드는 - 기호로 좋습니다만, 오브젝트가 아닌 클래스에 관련된 메소드의 선언이라면 + 기호를 지정합니다. - 기호의 메소드를 인스턴스메소드라고 부르고, + 기호로 시작하는 메소드를 클래스메소드라고 부릅니다. 인스턴스메소드와 클래스메소드의 차이점은 뒤에 자세히 설명하겠지만, 일반적으로 메소드는 - 로 시작한다고 기억해 주세요.
반환형을 보면 알겠지만, 메소드선언에는 형을 () 로 둘러쌉니다. 메소드가 인수를 받아들일 경우는 콜론 : 에 이어 가인수 리스트를 지정합니다. 가인수리스트도 통상의 변수선언과는 달리 변수형을 () 의 속에 지정하고, 그것에 이어 변수명을 지정합니다.
C언어의 함수의 기본반환형은 int 였습니다만, 메소드의 반환형의 기본값은 id 형이라고 하는 Objective-C 에 추가된 오브젝트를 나타내는 범용형이 되어있습니다. 반환형은 생략할 수 있습니다만, 통상적으로는 생략하지 않고 명시적으로 선언합시다. 반환값을 반환하지 않을 경우에는 (void)를 지정합니다.
- (void)method;
@end
이 Test 클래스의 선언은 반환값을 반환하지 않고, 인수를 받아들이지 않는 method 메소드를 선언하는 단순한 클래스를 선언합니다. 클래스명이나 메소드명의 명명규칙은, C언어의 변수나 구조체명의 명명규칙과 같이, 임의로 식별할수 잇는 알파벳부터 시작하는 식별자가 아니면 안됩니다. 단 관습적으로 클래스명은 대문자로 시작하고, 메소드명은 소문자로 시작합니다.
자, 클래스와 메소드를 무사히 선언할수 있었습니다만, 메소드는 메소드의 이름과 형만을 선언한 것만으로, 처리코드를 기술하는 정의가 존재하지 않습니다. 실은 Objective-C 에는 클래스의 선언과 정의가 완전히 분리되어져 있어, 클래스의 선언에는 인스턴스 변수와 메소드의 선언밖에 할수 없습니다. 클래스를 선언부터 정의와 구체화하는 것에는 @implementation 컴파일러디렉티브를 사용하여 클래스를 정의하지 않으면 안됩니다.
메소드정의
...
@end
@implementation 컴파일러 디렉티브에는 @interface 로 선언된 클래스의 실체를 기술합니다. 선언한 메소드는 여기에 정의되어지지 않으면 안됩니다. 클래스에 메소드가 선언되어져 있지 않은 경우에, @implementation 에 기술할 것은 아무것도 없겠지만, 그래도 정의되지 않은 클래스는 @implementation 에 명시적으로 실체되지 않으면 안됩니다.
클래스의 인스턴스화
클래스를 선언, 또는 정의한다면 클래스를 이용하는 일이 가능하게 됩니다만, 이대로는 사용할 수 없습니다. 클래스를 이용하기 위하여 필요한 메모리 영역을 할당하고, 적절한 초기화를 행하여 처음으로 클래스가 정상적으로 동작하게 됩니다. 클래스의 선언정보에 기초하여, 메모리를 할당하는 일을 인스턴스화라고 부르고 확보된 메모리영역을 인스턴스라고 부릅니다. 인스턴스라고 부르는 경우, 통상적으로는 클래스의 정보에 기초하여 확보된 실체를 나타내지만, 일반적으로는 오브젝트라고 부릅니다.
C++언어나 Java 언어등, 일반적인 오브젝트지향형언어에는 new연산자가 존재하고, 이 연산자가 클래스의 선언정보에 기초하여 인스탄스를 생성하고 초기화해줍니다. 그리고, 놀라운 것은 Objective-C언어는 인스탄스의 생성도 포함하여 클래스가 하지 않으면 안되게 정해져 있습니다. 그러나 클래스의 인스턴스화에는 오브젝트에 필요한 사이즈를 조사하고, 메모리를 할당하는 등, 번잡한 초기화처리가 필요합니다. 이것을 모든 클래스에 넣는 것은 현실적이 아니므로, 이작업을 일단 받아주는 것이 루트클래스의 존재인 것입니다.
Object 클래스는 Object 클래스를 포함한 그것을 계승하는 클래스의 인스턴스를 적절히 생성하는 alloc 클래스메소드를 정의합니다. 통상의 인스턴스메소드는 메소드를 불러내기 위하여 인스턴스가 필요하지만, 클래스메소드는 인스턴스가 아니라도 실행할 수 있다고 하는 성질이 있습니다. 그래서, alloc 메소드는 인스턴스가 존재하지 않아도 불러내도 문제는 없습니다. alloc 메소드는 인스턴스를 생성하기 위한 클래스메소드이기 때문에, 종종 팩토리 메소드라고도 불립니다.
이것이, Object 클래스에 선언되어있는 alloc메소드입니다. +로 시작하고 있기 때문에, 이 메소드는 클래스메소드인 것을 어필하고 있습니다. 반환형이 생략되어있기 때문에 디폴트의 id형이 반환됩니다.
id형은 오브젝트를 나타내는 범용형으로, 일종의 void * 와 같은 것이라고 생각해 주세요. 즉, 오브젝트의 클래스형이 어떤 것일 지라도, 모든 오브젝트는 id형의 변수로 보존할 수 있습니다.
자 이제, 클래스를 생성하기 위하여 alloc 메소드를 호출하지 않으면 안되지만, 메소드는 어떻게 불러내는 것일까요? C++계의 오브젝트지향언어를 경험한 많은 프로그래머는 직관적으로 다음과 같은 코드를 상상할 것입니다.
id obj = 클래스명.alloc();
유감스럽게도, Objective-C에는 많은 오브젝트지향형 언어에 채용된 이 기술방법은 잘못된 것입니다. Objective-C에서 클래스메소드를 부를때는 다음과 같이 기술하지 않으면 안 됩니다.
이것은, Smalltalk 언어를 오브젝트지향부분의 원칙이라고 하는 Objective-C의 특징입니다. 인스턴스메소드를 불러낼 경우는, 클래스명의 부분에 오브젝트를 지정하지 않으면 안 됩니다. C언어에서는 []는 배열의 요소를 지정하기 위하여 사용했었지만, 컴파일러는 []의 전후를 조사하여 메소드를 호출하는가, 배열의 요소지정인가를 판단할 수 있습니다.
이 메소드를 호출하기 위한 []를 메시지식이라고 부릅니다. Objective-C에는 오브젝트에서 (함수의 어드레스 등을 이용해) 메소드를 직접 불러내는 것이 아니라, 오브젝트에 대한 메소드에 관련된 메시지를 송신하고 있는 것입니다. 메시지식에 따라 오브젝트에 메시지가 송신되어지고, 오브젝트는 주어진 메시지에 따라 적절한 메소드를 기동하는 것입니다. 이같은 동적인 구조는 유연성을 확보하지만, C언어의 함수의 호출에 비해, 오버헤드는 배이상이 걸린다고 생각해 주세요. 물론, 컴파일러가 최적화등을 실시한 경우에는 이 한도는 없습니다만, 메시지에 따라 동적인 메소드의 호출은 실행시에 메소드를 검색하기 때문에 반듯이 오버헤드가 걸립니다.
#import <stdio.h>
#import <objc/Object.h>
@interface Test : Object
- (void)method;
@end
@implementation Test
- (void)method {
printf("Kitty on your lap\n");
}
@end
int main() {
id obj = [Test alloc];
[obj method];
return 0;
}
자, 이것이 간단한 Objective-C 에 의한 클래스의 실현입니다. @interface 에 의한 클래스의 선언에는, 루트클래스 Object를 계승하는 Test 클래스를 선언하고 있습니다. Test클래스에는 반환값을 리턴하지 않고, 인수를 받아들이지 않는 method 메소드를 선언하고 있습니다. 그렇게 때문에 @implementartion 에 이 메소드를 구현하지 않으면 안 됩니다.
클래스의 선언과 정의가 끝나면, 그 후 그 클래스를 이용하는 일을 할 수 있게 됩니다. main() 메소드에는 오브젝트를 격납하는 id형의 변수 obj를 선언하고, 동시에 Test 클래스의 인스탄스를 생성하여 이것을 대입합니다. [Test alloc] 에는 Test 클래스의 클래스메소드 alloc를 호출한다 라는 의미입니다. Test 클래스에 alloc 는 정의 되어 있지 않습니다만 alloc 메소드는 Object 루트클래스에 정의되어져 있기 때문에 정상적으로 동작합니다. alloc 메소드에는 Test 클래스의 선언정보에 기초하여 적절히 메모리를 할당하여 생성된 오브젝트를 반환해 줍니다.
Test 클래스는 인스탄스메소드 method를 정의하고 있기 때문에 생성한 오브젝트의 method 메소드를 메시지식에서 기동할수 있습니다. 프로그램에는 인스탄스생성 직후에 [obj method]라고 하는 메시지식을 기술하여 Test 클래스의 method 메소드를 기동하고 있습니다. 그 결과, 화면에는 Kitty on your lap 와 문자열이 표시될 것입니다.
덧붙여, 오브젝트를 사용하고 버리게 되는 경우, 인스탄스의 생성과 method 메소드의 호출은 다음과 같이 기술하는 것도 가능합니다.
이 경우, 내측의 [Test alloc]가 먼저 실행되어지고, 생성된 인스탄스를 참조하는 id형의 오브젝트가 반환됩니다. 그리고, 반환된 id형의 오브젝트에 대하여, 마침내 method 메시지를 송신하는 것으로 메소드를 호출하는 것입니다. 이처럼, 메시지식은 중첩되는 것이 가능합니다. 이것은 (Test . alloc()) . method() 와 같이 함수의 호출관계에 비교될 수 있을 것입니다.
상기의 프로그램처럼, 클래스의 선언과 정의의 장소는 자유이지만, 관습적으로 클래스의 선언은 헤더파일에, 정의는 클라스명과 같은 이름의 *.m 파일에 기술합니다.
2010년 1월 25일 월요일
2. 임포트
2. 임포트
새로운 프리프로세서 명령
Objective-C 언어는 C언어의 위에서 확장된 언어이기 때문에, C언어가 그대로 사용가능합니다. 보다 정확히는, Objective-C의 존재는 언어사양의 확장이 아니라, 컴파일러의 확장으로 최종적으로는 컴파일러는 Objective-C 언어의 코드를 C언어의 코드로 변환해서 처리합니다. 사실, 추가되어진 형이나 예약어도 사실상은 헤더파일에 #define 나 typedef 에 의해 정의되어 있는 것에 지나지 않습니다.
그래서, Objective-C 를 적절히 실행한는 것에는 정해져있는 헤더파일을 인클루드하지 않으면 안됩니다.Objective-C 에 새롭게 추가된 형이나 식별자는 objc/objc.h 헤더파일에 정의되어져 있습니다. 단, 이 헤더파일에 정의되어져 있는 기능은 Objective-C에 필요한 최소한의 것 뿐으로, 일반적으로는 컴파일러가 제공하는 총합적인 헤더파일을 인클루드하는 습관이 있습니다. GCC컴파일러에는 objc/Object.h 헤더파일을 Mac OS 의 Cocoa 개발환경에는 Foundation/NSObject.h 헤더파일을 인클루드하지 않으면 안됩니다.
Objective-C 컴파일러에는 존재하지 않는 코드를 기술하는 것에는 objc/objc.h를 인클루드합니다. 단, 이 기능만으로는 코드를 적을수 없기 때문에, 이때는 objc/Object.h를 인클루드합니다. 어째서 확장된 헤더파일이 필요한가에 대해서는 바로 뒤에 해설합니다.
Objective-C 에는 #include 프리프로세서디렉티브 대신 새로운 명령 #import 프리프로세서디렉티브 가 추가되어있습니다. 이 명령은 #include처럼 헤더파일을 인클루드합니다만, 한번 인클루드된 파일을 다시 인클루드 하지 않습니다. 그 이외에 대해서는 #include와 같은 기능입니다.
#import <헤더파일>
#import "헤더파일"
C 언어전용의 헤더파일을 인클루드할 때는 주의하지 않으면 안되지만, 많은 경우는 헤더파일을 다중인클루드할 필요는 없을 것입니다. 많은 헤더파일은 다중인클루드를 방지하기 위하여 프리프로세서명령을 지정하고 있을 것이기 때문에 #import라도 문제없을 것입니다.
이 이외에 대해서는 종래의 C언어와 같기 때문에 stdio.h 헤더파일을 인클루드해서 printf()등의 표준함수를 이용하는 일이 가능합니다. 단, Objective-C언어의 소스파일의 확장자는 원칙적으로 *.m 이라고 정해져 있습니다.
#import <stdio.h> #import <objc/Object.h> printf("the World 시간이여 멈춰랏!\n"); printf("WRYYYYYYYYYYYYーーーー\n"); }
int main() {
return 0;
이 프로그램을 보면 알겠지만, 실제로 C언어와 차이가 없습니다. Objective-C 는 C언어를 완전히 계승하고 있는 것입니다. C언어와 비슷한 언어가 아니라, 완전히 C언어와 호환성이 있습니다.
덧붙여, C언어의 코멘트 /* */ 에 추가하여, Objective-C에는 일행코멘트 // 가 추가되어 있습니다. 이 코멘트는 C++언어의 코멘트와 같이, C언어의 처리계에도 독자사양으로 채용되어있는 컴파일러도 많으므로, 모두들 알고 있을 것입니다.
//코멘트
Objective-C 에서는 이 코멘트를 사용할 수 있습니다.
2010년 1월 22일 금요일
1. Objective-C는?
1. Objective-C는?
오브젝트 지향형 C 언어
오브젝트 지향형 프로그래밍 언어라 한다면, 많은 사람들은 C++ 이나 Java, C# 언어를 떠올릴 겁니다. 언어계에 조금 마니악한 일본인이라면, Smalltalk 라고 답할지도 모릅니다. Object-C 도 Smalltalk 와 같지만 그 이상으로 마니악한 오브젝트 지향형의 프로그래밍 언어일 것입니다. 특히, AT호환기와 Windows 로 시스템을 구성하고 있는 기술자는, 이 언어에 접할 기회조차 없을지도 모릅니다.
그리나, 일반적으로 오브젝트지향언어라 한다면 Object-C지 라고 생각하고 있는 기술자도 존재합니다. 아마도 그 사람은 Mac OS 기술자이거나 스티브잡스의 팬일 것입니다. 현대의 컴퓨터로 가장 Object-C를 실용하고 있는 것은 Apple사의 Mac OS X 인 것입니다.
소프트웨어의 개발에 Object-C를 채용하고 있는 것은 Mac OX X 전용의 편리한 프리 소프트웨어가 인터넷에 공개되어있는 않은 원인의 한가지일지도 모릅니다. 어째서 이 같은 마이너한 언어를 사용하고 있는가 하면, Mac OS X 가 NeXT사의 NEXTSTEP의 개발언어로 해서 채용되어져 있다고 하는 역사적 이유입니다. Mac OS X의 GUI는 NEXTSTEP의 API를 이어받고 있기 때문에 개발언어도 주로 Object-C를 사용하고 있는 것입니다.
그러나 무서워할 필요는 없습니다. Object-C는 C언어와 완전히 호환성이 있는 언어로, C언어의 소스코드를 컴파일 할 수도 있습니다. 그리고 C언어에 오브젝트지향을 실현하기 위하여 어느 정도의 기능을 추가하고 있는 것입니다. 다행히도 Object-C의 오브젝트지향은 C++언어보다는 심플한 구성입니다.
또 여러 가지 언어의 해설 문서를 기술해 온 필자의 경험으로는 가장 학습수순의 구성이 어려운 언어였습니다. Object-C언어의 기본부분의 특정의 기능을 학습하기 위하여 Objective-C 언어전체의 구성을 이해하지 않으면 안된다고 하는 어려움이 있기 때문에, 오브젝트지향의 초심자는 이 언어의 기본부분의 본질을 이해하는 것은 곤란할 것입니다. 가능하다면 C++언어의 지식과 본질적인 오브젝트 지향의 이해가 필요합니다.
Objective-C 와 C++
Objective-C 는 C언어의 기본구조를 베이스로 해서, Smalltalk언어를 조합한 언어로, C++언어와는 역사적으로도 언어사양도 전혀 다른 존재입니다. 현대의 주요한 오브젝트 지향언어는 그 대부분이 Java언어를 베이스로 하고 있는 것이 많아, Smalltalk를 기본으로 하고 있는 Object-C의 코드를 보면 눈이 동그래 질 것입니다.
게다가, C++등의 다른 언어는 클래스의 실체의 메모리 구성 등을 은폐하는 것에 대하여, Object-C는 C언어를 기본으로 클래스를 실현하고 있기 때문에, 어느 정도의 구조가 C언어에서 보여집니다. 즉, 언어사양에 새롭게 오브젝트 지향적성질을 가한 현대의 오브젝트 지향형 언어에 반해, Object-C는 C언어에 디자인패턴으로 해서 오브젝트지향의 시스템을 추가했다라고 하는 입장이라고 생각할 수 있습니다.
Java나 C++에는, 클래스형의 개념이나 오브젝트의 생성방법을 언어사양으로 정하고 있습니다. 그러나 Object-C에서는 클래스형이나 생성방법조차 헤더파일에 정의되어져 있기 때문에, 그 실체는 C언어의 구조체를 typedef문으로 은폐하고 있을 뿐입니다. C언어에 친화성이 높은 것은 좋은 것이지만, 다른 오브젝트 지향언어를 습득하고 있는 기술자에게는 받아들이고 싶은 것이 있을지 모르겠습니다. 역으로 C언어프로그래밍에 오브젝트 지향을 디자인패턴으로서 채용하고 있는 것을 좋아하는 개발자에 한해서는 추가된 언어사양과 기반의 구조가 서포트되어 주므로 궁합이 좋을지도 모릅니다.
Objective-C 의 설치
Mac OS X를 이용하고 있는 것이 있다면, 부속된 개발환경을 인스톨하는 것으로 Object-C를 사용할 수 있습니다. 그러나 Object-C는 Mac OS X만을 위한 언어가 아닙니다. 놀랍게도 GCC 컴파일러라도 컴파일이 가능해서 Linux라도 이 언어를 이용할 수 있습니다. Windows라도, Windows전용으로 컴파일한다면 GCC컴파일러를 인스톨하는 것으로 사용이 가능합니다.
