반응형
반응형
클래스는 State와 Behavior를 선언한다.
State (Data)는 인스턴스 변수들을 통해서 관리된다.
Behavior는 함수를 통해 구현된다.
인스턴스 변수들은 일반적으로 숨겨져 있다.(getter/setter methods를 통해서만 접근할 수 있다.)

State는 flag, count와 같이 해당 객체의 상태를 나타내는 값으로, 변수들에 의해 관리되며,
Behavior는 이러한 State를 변경, 또는 조회하기 위한 통로를 제공한다.

[객체 메세지 전달]
객체에 명령을 주려면 그 객체에 명령 메시지를 보냄으로써 가능하다. Objective-C에서 메시지는 대괄호를 사용하여 표현한다.
[receiver message]
[receiver message:argument]
[receiver message:arg1 andArg:arg2]

여기서 수신자(Receiver)는 객체이고, 메시지(Message)는 어떤 명령을 할 것인지를 말해준다.

예를 들면 아래의 메시지는 myRect라는 객체에 display라는 메서드를 실행하라는 메시지 전달 표현이다.
[myRect display];


[myRect setWidth:20.2];
이 경우 메서드 이름에 콜론(:)을 붙이고 바로 인자를 넣으면 됨. 하지만 여러개의 인자를 받도록 정의된 함수의 경우에는 그 인자를 대표하는
키워드도 함께 써줘야함.
(함수 선언)
-(void)setOriginX:(NSFloat)originx y:(NSFloat)originy;

(함수 사용)
[myRect setOriginX:20.0 y:50.0];


[예제]
//Person이라는 클래스가 있다고 가정
Person *person;

//Person의 이름을 표시하는 함수를 호출하는 메시징
[person displayName];

//Person의 나이를 가져오는 메시징
int theAge = [person age];

//Person의 나이를 바꾸는 setAge 함수 호출
[person setAge:21];

//Person의 정보를 바꾸는 setInformation 함수 호출
[person setInformation:@"김철수" age:35];

//중첩된 표현(Nested Expression)
[myRect setPrimaryColor:[otherRect primaryColor]];


점(.)을 이용하는 방법
아래는 모두 같은 의미임
float height = [person height];
float height = person.height;

[person setHeight:newHeight];
person.height = newHeight;

[[person child]setHeight:newHeight];
person.child.height = newHeight;


* 정적 유형 객체는 클래스 포인터로 선언된다.
NSArray *myarray;
* 동적 유형 객체는 id로 선언된다.
id anObject;

동적 유형 객체의 클래스는 런타임 때 결정되므로, 개발자는 클래스에 관한 지식이 없어도 코드에서 객체를 참조할 수 있다는 장점이 있다.


[클래스 정의] Objective-C에서는 클래스를 크게 두 부분으로 나누어 정의한다.
* 정의부분(.h) - interface
* 구현부분(.m) - implementation

#import 와 @class의 차이점은
import는 상위 클래스 상속을 위해
class는 import할 수 있지 않은 상속 구조상에 있을 때 참조하고자 할 때



인스턴스 변수의 범위
@interface Worker  : NSObject {
    char *name;

@private
    int age;
    char *evaluation;

@protected
    id job;
    float wage;

@public
    id boss;
}




반응형
반응형

음 ㅇㅅㅇ, 질문 요청이 왔쯥니다.

지금 뭐 데굴거리고 있으니, 오늘 팀원중 중요하신 님아가 일이 있는날이라,

개 판치고 집에 가신 바람에 ㅇㅅㅇ, 일이 남습니담.(....으 =_=... 매달 한번씩..)

먹을거 잔득 사와서 다같이 놀다 가는날 ㅇㅅㅇ...


어쨌거나, 오브젝티브씨 강의이지만, 아이폰 프로젝트로 상콤 재빨리만들겠습니다.

따라할게 없으니 따라하지 마시구요. 설명만 들어주세욤 ㅇㅅㅇ,,


 

이름은 요렇게 주었구요..

우, 오랜만에 만지는 Xcode라 손이 익숙치가...

(그저께 손도 디었고...=_=)



어쨌거나, 만드시면 아래와 같은 것이 있답니담므 ㅇㅅㅇ

 


비어서 심심한지라 아래와 같이 뭘 만들어 주었어요.

클래스내 전역으로 선언한녀석입니다.

 


그리고 구현부에서 받아주었습니다.

그럼 이제 준비가 모두 끝났고 설명시작합니담 ㅇㅅㅇ

 


아래와 같이 전역으로 설정한 녀석들은 해당클래스 내에서 어떤 뿅뿅메소드가 사용을해도

상관이 없습니다. dealloc 에서도 사용가능하고, viewDidLoad 에서도 사용가능합니다.

 



그런데 첫번째 질문은 self가 뭔가요 ㅇㅅㅇ?

이었는데요.


self 는 "이건 내꺼임..!" 하고 분명하게 얘기해주는겁니다.

아래와 같이 self를 붙이건 안 붙이건 같은 효과가 납니다.


"헐, 그럼 안 붙여도 되네요?"

넴, 안 붙여도 됩니다만, 아이폰강의에 보면 디게 많이 붙어있을겁니다.

게임제작을 제외한 웹개발, 컴퓨터어플, 모바일어플 전체에서 저의 경우는 this(C에서는 this..!) 나 self 를 꼭꼭 써주는 버릇이 있습니다.

"강의 보니까, 안쓴것도 있던데요?"

[그건 귀찮아서리 ㅇㅅㅇ..]

"..."


어쨌거나, XNA의 메소드들처럼 메소드 하나의 인수가 7개 넘어가지 않는다면

그냥 this나 self를 박아주는게 이해하기 쉽고 좋다고 생각합니다.


그리고, 만약 해당 메소드내에 justButton이란 이름이 또 있다면 충돌이 발생하는데요.

그럴경우 해당 메소드에서 설정한 것을 우선으로 치기때문에, 그럴경우는 self를 꼭 써줘야죠 ㅇㅅㅇ

이러나 저러나, 써주는게 이익 >_<

 


근데 위를 보면 슈퍼가 굉장히 많습니다.

진 로마트, 홈플로스 익스프레스, 이마트 에브리데이에 쫗겨나가는 슈퍼가 여기는 왜이렇게 많은지

"..."

[개급니다. 안 웃어도 댐, 저만 웃음 댑니다.]

"....=_="

... 죄송요 ㅠㅜ...


어쨌거나, 슈퍼의 실체를 파악하기 위해서는 슈퍼에 대해 알아야합니다.

"ㅇㅅㅇ ?"

슈퍼라는 곳은 큰 기업들에서 물건을 받아서 제출하는 곳이지요 ㅇㅅㅇ...!

예를 들면, 슈퍼에서 싱싱한 캐비어를 판다고 칩니다.

"어찌하여?!"

재미용 ㅇㅅㅇ... 캐비어를 이제 상급 회사에서 넘겨주게 되겠죠.

그러면, 슈퍼는 그걸 팝니다.


뭐 별로 관계는 없지만, 프로그래밍의 슈퍼도 마찬가지입니다.

아래의 JustDescribeViewController라는 슈퍼는 상급회사로 UIViewController를 가지게된답니다.



오른쪽 버튼 클릭, 잡고 들어가보겠습니다.

 


음, 뭔지는 모르겠지만 많이 써있을겁니다.

 


찾다보시면, viewDidLoad 라는 분이 계실겁니다.

 


"오오, 다른것도 많아요 >_<"

 


총 아래와 같이 많이 있습니다.

"근데, dealloc은 없네요."

그건 또 그 상급회사에 있는게죠.

어쨌거나, 하위 회사에서 "super"하면, 그 위의 분이 가지고 있는 동일한 이름의 함수가 실행이 된답니다.




Super라는 메소드는 그 부모를 실행시키는 겁니다.

즉, 작은 슈퍼에서 "super!!"하면, 큰 슈퍼의 해당 메소드가 실행이되는 것이지요.


상속을 모르시는 분을 위해 썼는데 당연히 설명이 잘 되지 않는군요.

옆의 루비강의가 있습니다 ㅇㅅㅇ

맥을 사신분이라면 한번씩 해보시면 좋겠구요.

클 래스를 간단하게 설명했느니 보셔도 좋을 것 같습니다.


반응형
반응형

우선 강의를 하기전에 말씀 드립니당.

저는 일단 VMware라 너무 느려요...ㅡㅡ;; 쏘리쏘리 쏘쏘리... 그래서 컴파일 하나 하기도 힘들구

코딩하기두 힘들어서 흑흑흑... 흑.. 흑...OTL

 

그래서 결과를 제대로 보여드리지는 못하구요.

설명 위주로 하겠습니다.... 흑흑....ㅠㅠ

장학금을 꼭 따서.... 맥미니를 사겠습니다....ㅇ_ㅇ

근데, 학교공부는 언제하나....ㅎㅎ;;;

 

이제 아이폰 강의가 시작이 되었죠 ㅇㅅㅇ

그때그때 필요한걸 이 ObjectiveC강의란에서 하게 될 것입니다.

다음 강의를 위에 Property... 들어갑니다..!

 

우선 맥을 켜 주시구, 이제 Xcode가 2개네요 ~_~...

바탕화면은 웃어 넘겨주시구 ㅎㅎ ~_~;;;

 

 

우선 프로젝트 만드는 법을 까먹으셨을 수도 있으니, 차례차례 다시 합니닷 >ㅅ<

(사실, 그림이 너무 없어서, 이런걸로 그림 채우기...ㅎㅎ;;)

 

 

Command Line Tool - Foundation 선택 하시구요.

 

 

제목은 Property Test입니다.

상콤하게 만들어 주시구요.

제가 Xcode를 힘들게 힘들게 쓰다보니 거의 사상언어를 쓰는 편입니다.

(사상언어 : 머릿속에서 플레이 하는 프로그래밍 언어. 이런 용어는 밖에서 쓰이지 않으니 쓰지 마심므)

(아리스토텔레스인가 뭐시기인가의 사고실험에서 영감을 얻은 단어...ㅡㅡ;)

 

사상언어를 쓰시다보면, 에러코드도 안 만드는 연습도 하구, 뭐 괜찮습니다 ~_~

닥치고 빨리 맥 미니가 필요하다.... 돈이 없서...ㅍ_ㅍ

 

 

상콩하게 오른족 버튼 누르시구 New File을 눌러줍니다.

예제는 그냥 저번것 비슷한 Car 예제를 사용하겠습니다.

 

 

Objective-C Class를 선택해주시고

NSObject의 상속을 받읍시다.

 

아, ObjectiveC강의를 지금 보시고 계시다면

JAVA 꼭 해보시기를....

ObjectiveC와 완전히 같습니다. ~_~(거의 90% 가량..)

(맥 미니가 없어서, 맥으로 잘 못해 죄송한 마음으로.... 자바강의는 열심히 쓸게요...ㅠㅠ)

 

 

제목은 역시나 지금 만들고 있는 프로그램과 비슷한 Car.m..!

 

 

그럼 상콤하게 아래와 같이 쳐주십니다. 가 아니고, 제가 쳐다가 키도그 집어 던질 뻔 했습니다..ㅡㅡ;;

(지금 이 강의를 보시는 중에 맥제품을 쓰고 계신다면 부럽군염...ㅠㅠ)

일단 Setter와 Getter의 개념에 대해 알아보도록 합시다.

 

객체를 생성하고 다음과 같이 그냥 접근하면 불가능 하다고 난리를 치십니당.

 

 

그래서, Getter/Setter가 필요합니다 ~_~

(걍 만드는겁니다 ~_~, ObjectiveC에서는 일반 변수는 겟터가 변수이름과 같습니당.)

 

Car.h

 #import <Foundation/Foundation.h>

@interface Car : NSObject{
  int num;
  int in_time;
  int out_time;
  int money;
}

-(void) setNum;
-(int) getNum;
-(void) setIn_time;
-(int) getIn_time;
-(void) setOut_time;
-(int) getOut_time;
-(void) setMonet;
-(int) getMoney;

@end

 

Car.m

 #import "Car.h"

@implementation Car
-(int) getNum() {
 return num;
}
-(void) setNum:int n {
 num = n;
}
-(int) getIn_time() {
 return in_time;
}
-(void) setIn_time:int i {
 in_time = i;
}
-(int) getOut_time() {
 return out_time;
}
-(void) setOut_time:int o {
 out_time = o;
}
-(int) getMoney() {
 return money;
}
-(void) setMoney:int m {
 money = m;
}
@end

 

쓰시지 마시구요. ㅋㅋ;; 계속 읽어주세요 >ㅅ<

 

우선, Setter와 Getter에 대해서 알아보도록합시다.

저는 프로그래밍을 공부하면서,

"외부에서 직접접근하면 안됨므, 일단 private써야함므" 라고 하면 항상

"왜요?" 라고 물었습니다.

 

1. 캡슐화, 캡슐화, 실수해서 안에있는 데이터를 바꿀 수도 있구.

2. 우리가 전자제품의 부품을 볼 필요는 없잖니.

 

하는데 저는 살면서 그런 빠가같은 실수를 해본적이 없습니다 ~_~...

(뭐 솔직히 말해서, const나 final 이용한 변수 바꾼적도 없음므...ㅡㅡ;;)

부품 알면 좋지, 왜 보면 안되는 거지...

왜 그래야 하는가, 그냥 public해서 접근해도 되는데

왜 private 선언해버리고 getter/setter를 설정하는가에 대한 고민을 심각하게 한 적이 있었습니다.

 

뭐 정확한 답은 내지 못했구요.

간단하게 "다 그렇게 하니까."로 답을 냈습니다.

"완전 무책임 해...!!!"

하하하 제길...ㅡㅡ 이걸로 아는 누나하고 싸운적도 있어요.

 

"ㅎㅎ 객체의 안을 알 필요는 없잖니, 그냥 쓰면 되는거지."

"알아서 나쁠건 없잖아요."

"ㅎㅎ 그러다 잘못 건드리면 어떻게해?"

"어떤 병이 그걸 잘못 건드려요"

"..안 건드릴거면 private 써...!!"

"~_~ 잉, 그냥 public 선언하"

"닥쳐!"

 

이런 적도 있답니당. ~_~ 다른사람이 다 그러니 우리도 그럽시다.

ObjectiveC에서는 자동으로 Private 선언됩니다.

 

그래서 Getter/Setter가 필요합니다.

물론 Getter와 Setter가 있어서 편리한 점도 있습니다.

 

예를들어 헬로키티 인형의 "수"가 속성(변수)입니다. 그럼 음수가 떠서는 안되겠죠??

(왜 하필 예가 이따위냐면, 제가 헬로키티의 매니아이기 때문이죠.... 작년에 연씨한테 감염)

 

헬로키 티.jpg

더있지만, 빼면 안되는 위치에 있어서 ~_~

 

그럼 여기에

 

-(void) set인형:int 인형수 {

          if(인형수>0){
               인 형 = 인형수;

          } else {

               NSLog(@"개념좀 챙기고 입력하심므");

          }
}

 

이런 식으로 만들수가 있겠죠 ~_~

 

그럼 이제 자바를 하신 분들이 들고 일어납니다.

"이클립스는 그냥 만들어 주는데, Xcode는 그런거 없나요?!"

 

물론 당연히 있습니다...!!

 

(쓰다가 던진 화면.jpg....) 넘어가구요..ㅡㅡ;;

 

그럼 자동으로는 어떻게 생성하나..?!

면 바로바로 Property입니다.

 

아래와 같이 @property / @synthesize를 입력해 줍니다.

 

 

그럼이제 된겁니다.

"엥, 뭐가 된건데요?"

아까 에러가난 부분을 다시 봅시다.

 

이제 문제없이 진행이 됩니당. 우앗 >ㅅ<

신기신기 동방신기

(뭔 개소리야...ㅡㅡ;;)

 

 

그리고 이제는 setter도 자동으로 만들어졌습니다.

아래와 같이요 >ㅅ< 룰루~

자동으로 엔터치면 입력이 쑤루루 되죠 ㅎㅎ

 

 

다른것두 마찬가지 ~_~

 

 

메모리 해제는 잊지마시구 하시구염. 아래와 같이...ㅎ

 

 

어쨌거나 오늘 강의도 끝 ~_~

그럼 다음번에는 이 Property를 사용한 iPhone 강의가 진행이 되겠지요 ~_~

VMware의 상태가 안 좋으면 저번에 만든거 위에 그림하나 넣고 끝날쑤두...ㅡㅡ;;;

 

원래 더 자세하게 보려구 했는데요...ㅠㅠ

힘드네용 OTL(맥 너무 비싸염 ㅠㅠ...그러니 PC에 밀렸지....ㅠㅠ)

 

프로퍼티랑, 신데사이저 쓰면 그냥 저렇게 된다는 것만 인지하시구요 ~_~

아이폰 강의에서 어떻게 활용하는지 보도록 하점..

...근데 보셨으면 ...리.. 리플점 ..ㅠㅠ

반응형

'Mobile > Object-C' 카테고리의 다른 글

[Study 1]  (0) 2010.10.20
ObjectiveC 11강 - Self와 Super  (0) 2010.10.01
ObjectiveC 9강 - 본격적인 객체지향 프로그래밍  (0) 2010.10.01
ObjectiveC 8강 - 조건, 반복문  (0) 2010.10.01
ObjectiveC 7강 - 데이터형과 표현식  (0) 2010.10.01
반응형

이런 제길슨, 컴퓨터가 또 뻑갔어염.

노트북 씨로 씁니다 ㅠㅠ.. 이거 뭐, 2주에 한번씩 가주시네염.

(덕분에 2주에 한번씩 하드웨어 업그레이드 및 포멧....)(좋은 것은 아닌듯 OTL)

 

지금까지 ObjectiveC강의는 거의, 그냥 C강의와 겹쳤죠.(2강의만 제외하고)

그렇지만, 이제부터는 본격적으로 C강의와 다른 루트로 가게 되겠습니다.>ㅅ<

어떻게 진행을 할지 또 한주간 생각을 했는데요.

객체지향과 관련된 간단한 프로그램을 만들고, 아이폰에까지 그 프로그램을 옮긴뒤

이 강의를 종료하겠습니다.(이 강의의 목적 자체가 원래 아이폰 프로그래밍이니까요.)

(아마 JAVA강의도 완전히 같은 방식으로 진행이 되겠습니다. 같은 프로그램을 만들고, 안드로이드로 옮기고 끝)(그리고 나서 아이폰과 안드로이드를 진행하겠습니다...ㅎ)

 

그럼 우리가 만들 객체지향 프로그램이 무엇이냐...!

바로바로 -주차장 관리 프로그램-입니다.

지난번에 객체에 대해서 약간 설명을 했었는데, "미친넘아, 더 헷갈리잖아"하는 아는 분이 있어서

간단하게 개념을 다시 잡고 들어가도록 하겠습니다....ㅠㅠ

몇 일간 강의는 이야기 형식으로 풀이를 하겠습니다.

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

어느날 나씨가 저에게 와서 제안을 해요.

"내가 땅이 많은데, 할게 없다. 심심해, 주차장 관리나 하렴"

"왓?! 내가 왜 주차장을..."

"노예계약"

"넵, 근데 뭐 신청해야 하는거 아닙니까?"

"다 했음, 알아서 하심, 요 앞에 공터에 주차장 마크 붙여놨으니까, 내일부터 알아서 하려무나."

해서 주차장 관리를 시작하게 되었습니다.

 

그런데, 뭘 어떻게 해야 하는지, 바보같기도 하지만 똑똑한 연씨에게 가서 대화를 합니다.

"뭘 어떻게 해야 하는 걸까?"

"ㅋㄷㅋㄷ, 그냥 돈 받으면 되는거 아냐?"

 

다음날 주차장을 갔습니다.

차들이 들어와요.

차들이 나가요, 돈을 받아요. 근데 모두 똑같은 값을 받았더니, 와서 죽치고 앉아 있네요.

뭐, 나랑 상관이 있을까. 그냥 냅두고 있는데, 나씨가 와요.

(참고로, 제가 말하는 나씨는 여자에요. 만약 이 글을 본다면 찔끔 할듯.)

나씨한테 싸닥션을 맞았어요.

한번쯤 반항해 줘요.

"뭘 어떻게 해야 하는건데요?!"

"대충 정보는 적어줘야 할거아냐?!"

"아...."

그랬어요, 이제 정보를 적어 보기로 했습니다.

 

다시 연씨와 상의를 합니다.

"무슨 정보를 적어야 할까?"

같이 상의를 하고, 어떤 내용을 적을지 연씨랑 같이 생각을 합니다.

음음,

"나는 나는, 자동차 빨간색이 좋아 >ㅅ<"

"아.. 색.. 그럼 엔진종류 같은 것도 쓰는건가?"

"회사두 쓰구"

"배기량 같은 것두..?"

(실제로 이런 빠가들이 아님을 알려드립니다.)

"오, 이제 뭔가 되는 것 같아."

"ㅋㄷㅋㄷ"

다시 주차장으로 갑니다.

 

저기 자동차 한대가 들어옵니다.

적기 시작해요.

자동차 이름 : YF소나타

자동차 색 : 정열의 붉은색

회사 : 현대

엔진종류 : 그걸 내가 어떻게알아

배기량 : 그걸 내가 어떻게 알아

자동차가 나가길래 3000원을 받습니다.

한국 소비자를 봉으로 하는 현대라 5000원을 받을까도 고민했지만,

그건 너무 한 것같아 그만두었습니다.(...ㅡㅡ;;)

 

잠시후에 제가 뭘 적도 있으니 나씨가 흐뭇한 표정으로 저에게 다가옵니다.

저두 흐믓하게 그녀를 바라봅니다. 나씨는 제가 적고 있는 것을 보더니 웃습니다.

"하하하.....하!"

다시한번 공포의 싸닥션을 맞았어요.

"왜 때려요?!"

다시 한번 반항을 해보지만. 소용 없는 일이라는걸 항상 깨달음...

"... 빠가야, 저기 다 른 동네 주차장 구경 좀 하구와라."(아주 중요한 말입니다.)

연씨랑 손을 잡고 랄랄라 하고 다른 주차장 구경을 갑니다.

주차장 아저씨 뒷목에 맥스봉을 겨누

고 총인냥 위협하며 말했습니다..

"자눼는, 여기서 무엇을 하는가."

아저씨는 총인줄 알고 덜덜덜 떨면서 말해요.

"...도.. 돈 받는데"

(이런 미친일은 현실에서 일어나지 않습니다. 따라하지 마세요.)

(저번주에 출발 비디오여행인가 보는데 나온거..)

"어떤식으로..?"

"...초.. 총은 내려놓고 말하지 않겠나."

"일 진행 해보세요."

그렇게 맥스봉을 아저씨 뒷목에 하루종일 겨누고 아저씨가 뭘하는지 구경을 했습니다.

『차가 들어온다 →

   차 번호와 출입시간을 적는다. →

   기다린다. →

   차가 나갈 때 나가는 시간을 적고 계산해서 돈을 받는다.』

아, 이제 뭘 적어야 하는지 알 것 같아요.

 

이렇게 적고 있는데 또 나씨가 옵니다.

또 싸닥션을 맞지 않을까 하고 긴장을 빨고 있는데 나씨가 와서 얘기합니다.

"잘 하구 있군하."

이제 왠지 안심이 되여.(전 등심이..)

"근데, 이걸 왜 다 쓰고있냐? 앞에 것만 프린트 해서 딱딱 쓰면 되는거 아냐?"

앗 이런, 나이스한 아이디어, 저는 그날 집에가서 엑셀을 키고 Ctrl+C, Ctrl+V 신공을 사용합니다.

 

짜자잔~! 이제 쉽게 쉽게 할 수  있을 것 같습니다...!

그리구 이 종이를 들고 랄랄라 주차장으로 다시 출근을 해서 열심히 일을 합니다.

 

연필을 잡고 쓰다보니 손이 아파서 낑낑거리구 있을때

나씨가 와서 얘기합니다.

"병아, 너 명색이 "프로그래머"인데, 프로그램 짜지?"

"....아.. 근데 여기 컴퓨터가 없잖아여"

"~_~ 그럼 모바일로 짜서 와서 끄적여도 되잖아."

"......ㅇ_ㅇ"

그리고 프로그램을 짜기 시작합니다.

=========================================================================================

그럼 우선 이게 프로그래밍이랑은 뭔 관련이고 뭐가 어떻다는건지... 이해가 안되실 겁니다.

프로그래밍을 함에 있어서 객체지향을 도입하게 된 이유는

현실 세계를 모방하기 위해서 입니다.

 

우리가 사는 이 "현실"이라는 곳은 객체와 객체가 모여서 이루어지고

객체끼리 상호작용이 일어나는 곳이죠.(그럼으로 자연을 사랑해야하는거....ㅇ_ㅇ??)

 

지금 위의 이야기에서는 "주차장"프로그램을 짜게 됩니다.

현실의 "주차장", 현실의 "자동차"가 있겠죠.

객체지향 로그래밍이란 간단히,

컴퓨터 상에, 프로그래머는 가상의 "주차장", 가상의 "자동차"를 만드는 겁니다.

간단하죠 ~_~...?

 

객체는 많은 것을 가질 수 있습니다.

위의 자동차 예를 들면, 색이라던지, 회사라던지, 바퀴모양, 엔진은 어떤 것을 쓰고 등등

하지만 프로그래밍을 함에 있어서 그 "모든 것"에 주목하지는 않습니다.

우리가 주목할 것은 "우리가 원하는 것"입니다.

그 "우리가 원하는 것"을 알기위해 많은 조사를 해야하고, ...이걸 뭐라하더라,

어쨌거나 오랜 시간을 들여 연구를 합니다.

은행관련프로그램이라면, 은행에 가서 뒹굴어야하고

학생관리프로그램이라면, 학교에서 뒹굴어야할 것입니다.

이러한 많은 조사를 통해, "우리가 원하는 것"을 추출해내야 하죠.

 

이 "우리가 원하는 것"을 "속성"이라구 하구요, 간단하게 객체의 변수라고도 합니다.

 

위의 이야기에서 보면 저 종이에 적혀있는 4가지 것들이 객체의 변수이죠.

자동차에게는 수많은 속성이 있겠지만, 우리는 주차장에서 필요한 4가지 속성만 뽑아내 보았습니다.

이제 저 종이 각각은 "객체"가 된 것이죠.

 

간단하게 보면 객체라고 할 수 있겠지만, 저런 종이 상태로는 "메소드"가 없죠 ~_~

그건 다음 강의에 알아보도록 하구요.

 

오늘은 간단히 살펴보고 끝냅시다..!

--------------------------------------------------여기까지는 JAVA강의와 같습니다.---------

(물론 아직 자바 강의가 없지마능 ㅋㅋ)

 

 

우선 프로젝트를 만들도록 합시다.

오랜만에 하는거니 조금 세세하게 알아보도록 하죠 ~_~

 

 

프로젝트의 이름은 "주차장"이미, Parking 이라구 주었습니다.

 

 

그럼 예제를 작성하겠습니다.

 #import <Foundation/Foundation.h>

int main (int argc, const char * argv[]) {
    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];

    // insert code here...
    int number;
    int in_time;
    int out_time;
    int money;
    /////////////////////////////////
    number=2734;
    in_time=12;
    ////////////////////////////////
    out_time=15;
    money=(out_time-in_time)*1000;
    printf("************************\n");
    printf("차량번호 : %d\n",number);
    printf("입차시간 : %d 시\n",in_time);
    printf("출차시간 : %d 시\n",out_time);
    printf("최종요금 : %d 원\n",money);
 
    [pool drain];
    return 0;
}

요것 입니다 ㅎㅎ

일단 원래 하던 것과 별 다를바가 없습니다.

 

 

넣으면 쑤쑤 들어가서 출력을 해줍니다.

...예제의 복사를 위해 윈도우와 공유한뒤에, Txt 파일루 저장했습니다 ~_~

 

===========================================================================================

그런데 프로그램을 짜고 있는데, 구씨가 와서 얘기 합니다.

"뭐하냐?"

"프로그램 짭니당"

"~_~, 2대 들어가면 어쩌려구?"

".... 뭐 그냥..."

 

 

"이렇게 하면 되는게..."

"..."

"그렇죠, 아니겠죠. 코딩이 완전 길고 짜증나구 뿌뿌스럽군요"

===========================================================================================

자, 그럼 여기서 C를 공부 하셨던 분이면 "구조체"쓰면 되는거 아님?

하실 겁니다. ~_~

넹, 그렇스므니다. 구조체를 쓰면 됩니다.

하지만 우리는 다음 강의를 위해서 일단 "클래스"를 생성하겠습니다.

 

상콤하게 소스에서 오른쪽버튼을 눌러서 새로 파일을 만들어 줍니다.

 

 

딱 알아서 이름이 써있네요.

Objective-C Class..!

만들어 줍니다.

NSObject에 대해서는 나중에 알아보도록하구 일단 선택해줍니다 ~_~

 

 

이름은 자동차니까 Car.m으로 주어주시구요 ~_~

 

 

확인 누르면 아래와 같이

car.m/car.h가 생성이 됩니다.

간단히 car.h에는 선언만 해두고, car.m에는 선언한걸 풀어서 설명하는 거죠 ~_~

 

 

일단 오늘의 수업은 메소드 설명 전까지 나갈 겁니다 ~_~

일단은 아래와 같이 만들어주세영.

제가 직접 만든 예제니까, 저작권 문제는 없을거에요 ㅋ...(이게 너무 무서워 ㅎㄷㄷ)

 

...꺼졌다.. ~_~ 어쨌거나 다 했으니... 아마두 이게 Car.h

#import<Foundation/Foundation.h>

 

@interface Car : NSObject {
    int number;
    int in_time;
    int out_time;
    int money;
}
-(void) carIn:(int)n:(int)i;
-(void) carOut:(int)o;
@end

 

Car.m

 #import "Car.h"


@implementation Car
-(void) carIn :(int)n:(int)i
{
    number=n;
    in_time=i;
    return;
}
-(void) carOut: (int)o
{
    out_time=o;
    money=(out_time-in_time)*1000;
    printf("************************\n");
    printf("차량번호 : %d\n",number);
    printf("입차시간 : %d 시\n",in_time);
    printf("출차시간 : %d 시\n",out_time);
    printf("최종요금 : %d 원\n",money);
    return;
}
@end

 

메인입니다.

 #import <Foundation/Foundation.h>
#import "Car.h"

int main (int argc, const char * argv[]) {
    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];

    // insert code here...
    Car *car1=[[Car alloc]init];
    [car1 carIn:2734:13];
    [car1 carOut:15];
    [car1 release];
 
    [pool drain];
    return 0;
}

실행 화면 입니다. 위의것과 같죠..?!

일단 클래스에 관한 문법은 나중에 알아보도록 하구요.....

 

예전시간에 대충 객체생성방법을 배웠습니다.

스스로 한번 분석해 보시구요....OTL

 

원래 분석까지 하구 마치려구 했는데 학교 물리숙제땜시... 빠빠여 >ㅅ<

다음주에 뵈영...ㅇ_ㅇ?!

물리 숙제 빨리 끝나면 아마두 내일 C-For문으로 * 삼각형 만들기 강의가 진행될듯...!

 


반응형
반응형

C 간단히 강의에.. 있어서영.... 안 할라구 했는데

저번 강의에 상관없이 나간다고 했잖습니까....ㅎㅎ

그래서, 예제 몇개만 해보고 넘어가도록 합시다..!

 

일단은 조건문 예제 입니다 ~_~

 

 

그리구 실행 결과...

음 ~_~ 설명을.. 하지 않아도 될 것 같습니다.

죄성해요 ㅠㅠ  C언어 간단히 예제를 봐주세영 ㅎㅎ;;

 

 

일단 이 예제는... 만약 우리학교 학생이 보고 있다면 주의 깊게 보세요 ~_~

아니다, 다른 학교도.. 아마 중간고사 범위까지로 봐서는... 이거 낼 것 같은데....

별로 삼각형 만들기... C언어 자세히 강의에서 여러가지 모양을 만드는걸 강의해볼 생각...ㅎㅎ;;

 

 

왜 printf() 씁니까?!

걍 썼어요 ~_~ 어차피 이것두 C니까요..!

Objective... "C"

~_~ 실행 쭉쭉 되죠.

 

 

다음은 while()문 예제

C 간단히 강의에서 했었던 것 같은 예제입니다..ㅎㅎ(아.. 아닌가..?)

...했던듯 조금 코드는 달라도...~_~

 

 

실행 결과 입니다.

 

 

위의 예제 출처는 혼자연구하는 C/C++에 있는 예제구요.

그냥 약간 변형만 있을뿐... 어쨌거나 저작권을 밝혀둡니다. ㅋ

 

다음 강의부터는 본격적으로 간단히 강의와 다른 진도로 나가게 됩니다...

"우와와와"

그래서, 1주일에 1번 올릴게요 ~_~....

 

월요일부터 학교에 그냥 8시까지 가서 공부하다가 수업 듣고 학교 끝나면 학원가구

학원 7시30분부터 10시30분까지 >ㅅ<

그리고 강남역에서 집까지..음 ~_~ 1시간?

그럼 11시 30분 도착, 12시 취침이니까...

(헐킈, 그럼 강의 언제씀므?!)

어쨌거나... 평일에 연구를 하구요. 주말에 쭉쭉 쓰겠습니다.

C언어 간단히 강의의 퀄리티도 상당히올라갔죠?

열심히 학교 네이버실...(네이버.... 뭐라고 부르는지 모르겠지만 네이버 지원실)에서 연구중이니까요.

 

저두 공부를 하구 ~_~

보시는 분이 있다면 보시는 분도 도움이되고.

(슈프림커맨더2로 인한 유입이 더 많다는 점에서 이미 좌절했음...ㅋㅋ)

 

그럼 오늘강의.. 대충은 아니라구 믿어요 ~_~

간단한거니까요..!

 

그렴 뺘뺘

반응형
반응형

~_~ 뭐, 3월 2일부터 하겠다고 했지만

전직 키보드워리어였던 저의 손가락이 허락하지 않네요.

 

사실은, 알려드린 사이트

작가 자신도 책을 팔아야하니

소스를 조금씩 잘라먹고 올렸더라구요 ~_~

C언어를 하신 분은 고치거나 추가가 가능하실텐데,

프로그래밍 언어를 처음공부하시는 분들은 당황하실 수 있기에, 빨리 이 글올려서 당황을 막고자...

 

오늘은, 저번 커리큘럼의 2일차. 데이터형과 표현식에 대해 알아보도록 하겠습니다 ~_~

(C언어 강의와 비슷한 수준의 강의가 될 겁니다. ~_~)

 

               
 

정수형

int %i        
 

문자형

char %c %x %o    
 

실수형

float %f %e %g %a  
    double %f %e %g %a  
 

객체형

id ~_~        
               

 

그럼 일단 오늘의...(뭐야, 엑셀 복사 되잖아..~_~)

강의 전체 내용입니다. 별거 없죠..?!

C언어와 거의 같습니다.]

 

그럼 일단 예제보면서 시작하도록 하죠 ~_~ ㅎㅎ

이 ObjectiveC 강좌를 보고 계시다면 아마... C는 한 상태겠죠?!

(처음이라면 죄송 ~_~ 그러시면 C강의를 보시구)(C강의...자세히 강좌는 3월 2일부터.....;;)

(뭐, 보는 사람이 없으니...;;)

 

어쨌거나 그럼 int부터 갑니다.

 

간단한 예제입니다.(일부로 간단하게... 해킨토씨 뻑갔어요 ~_~)

어쨌거나, VC++에 적었다고 VC++로 적고 실행시키시면 안됩니다 ㅎㅎ

 

자료형 이름;

의 방식으로 변수를 설정합니다. C언어와 같습니다.

변수가 뭔지는 http://blog.naver.com/yooninsung/30080384024 을 들어가서 보세요 ~_~

 

 

int는 정수값입니다. 정수란 그냥 1923812093791203이런 숫자죠. 소숫점이 없는 숫자..!

일단 출력할때는 "%i"를 사용합니다. %i와 같은 것을 서식문자라고 하여

앞으로 무엇을 출력할지 결정해주는 겁니다. 순서대로 그 뒤부터 ","를 쓰고 해당하는

변수, 또는 상수를 입력해줍니다. 위에서는 "a"가 int형이니 %i를 사용한 겁니다.

 

위의 표를 보면 %i, %x, %o가 있는데요.

%i : 10진법으로 출력 

%x : 16진법으로 출력

%o : 8진법으로 출력

입니다. ~_~(외워야하는지 여부는... 나머지는 그냥 심심하면 외우시구요, %i는 외웁시다.

 

다음 예제는 저번 사이트에서 가져온 예제입니다. float에 대한 건데요.

float형인데요. 출력시 %f를 사용합니다.

실수는 "."이 있는 수죠. 123.002 이런거요.

아래 예제를 보시면 %f가 두번 나왔는데요, 순서대로 뒤에있는 변수와 연결이 됩니다.

 

 

다음은 %e,  마찬가지로 나누기를 뚝뚝 하고나면 실수값이 나오게 됩니다 ~_~

근데 자릿수가 너무 뿡뿡해지니, 과학적표기법을 사용하게 되는 겁니다.

(하지만, 전 살면서 써본적이 없답니다 ~_~... 이런말 하면 안되는뎅)

 

 

"그럼 double은 뭔가요?!"

float이랑 똑같은데, 더 많은 숫자 범위를 담을 수 있습니다. ~_~

그냥 float이랑 같아요. ~_~ 용량만 다를뿐

 

다음은 char의 예제

char은 %c로 출력합니다.(참쉽죠, 앞에있는 글자로 그냥 출력해버니..)

 

다음은 id의 사용법입니다.

저번에 했었죠 ~_~ interface부, implement부, main부 해서...

 

이 예제가, 제가 알려드린 사이트에 올려진 대로 쓸 경우 에러가 뜨는 예제입니다.

다른 예제처럼 스크린샷을 찍고 올려서 보는데

"어라, 이게 실행이 된다고?" 해서 열심히 다시 해킨을 깔아 실행해보니, 안되더군요 ~_~

이건 예제를 고쳤으니 잘 될겁니다.(실행해봤으니까요.)

 

다다다음 강의에서, interface가 뭐고 implement가 뭐인지 할테니까요 ~_~

4강에서 너무 대충했던듯...

그 전에는 일단 이런게 있군하 하고 보면서 그냥 익숙해져 주세요 >_<

이 예제는 지금 이해 못하셔도 상관없습니다.

다다다음 강의에서 또 나오실 몸이니까요.;;

 

 

그럼 데이터형 설명 끝....;;

만약에 이 이상 공부하고 싶으시다면

www.winapi.co.kr 에 들어가서 C언어 강의에 나오는 자료형파트를 읽어보세요 >_<

 

표현식은 상수표현식과 변수 표현식으로 나뉩니다.

[1 + 3 + 4 - 2]

와 같은 것을 상수 표현식이라고 합니다.

변수 표현식은 상수표현식 안에 변수가 하나라도 들어갈 경우 부르는 말입니다.

[a + 1 + 3 - 2]

와 같이요, 뭐 별거 없군요...ㅎㅎ

 

그럼 오늘의 강의는 여기까지 ~_~

...대충..아니죠..?(저는 그렇게 생각...ㅡㅡ;:)

C언어 강의에 비해서는 대충이지만, C언어를 모르시는 상태에서 이거 나가는건....

조금 그렇구요.... 간단히강의 정도 한번 같이 나가주세요.

 


반응형
반응형
그런거 엄뜸
반응형
반응형
여러가지 고민을 많이 했습니다 ~_~
 
지 금부터 할 내용의 절반이 C언어와 같은데 그걸 해야할까 말아야할까...ㅡㅡ;;
 
결 론은 안하기로 결정~!
" 우아아악 뭡니까..!!"
" 어차피 객체지향C를 공부하려면 절차지향C는 공부하고 와야죠 ~_~ C간단히 강의 살짝 훑고 오세염"
(오... 간단히 강의를 이런 방식으로 사용할 수 있군요. ㅡㅡ;;)
 
어 쨌거나, 다음 6강을 나가기 전에 ~_~
(클 래스부터 나갈겁니다.)
(" 아니, 그래놓고서 [아, C++이랑 똑같네염, C++강의 보세요.] 이러는거 아닌가염?!")
("C++ 강의 안 할겁니다... ~_~ 다음 여름방학 때 할 수 있음, 해보겠지만...")
 
적 응이 잘 안되는 Xcode를 잘 적응해 봐야겠죠 ~_~
http://classroomm.com/objective-c/
이 사이트로 들어가셔서
 
저 여우 꼬리가 가르키는 곳을 누르시고

 
들 어가시면

 
요 렇게, 소스들을 볼 수 있습니다 ~_~
열 심히, 보고, 열심히 치고, 열심히 익숙해지고, C언어와 공통점과 차이점을 파악합시다 ㅎㅎ
 
보 시다보면 막 scanf()쓰고 등등 하니까요. 열심히 보고 ~_~ 열심히 쓰세요.
복 사하는건, 공부가 아닙니다. 지금 연습하는 거니까, 치세요 ㅎㅎ
음 악을 배울 때도 강의만 듣는다고 되는게 아닌 것 처럼
프 로그래밍언어를 배울때도, 직접 실습하면서 합시다. ㅎㅎ...
 
자, 그럼 다음강의부터 저작권따위는 없다...ㅡㅡ 지식인에 물어봐서 확인했는데... 상관없다는군요.
게 다가 저는 그 책을 베끼는 것이 아니라, 위의 사이트에 올라온 예제를 베끼는 거랍니다 ~_~
ㅎ ㅎ ㅎㅎ ㅎㅎ ㅎㅎ 그럼 1주일 있다가 뵈용.
 
시 작할때 말했듯이, 저두 ObjectiveC 처음 공부한답니다 ~_~
1 주일간 책 2권 끝내고, 자세하고 정리된 강의로 뵐게요 ㅎㅎ
아 이폰강좌가 병행해서 나가게 되겠군요 >_<
 
그 럼 오늘강의는 여기서 빠빠이
죄 송죄송 합니다 ~_~
크 리스피도넛 46% 할일땜에 정신이 나갔나봐요 ;;; 
 
그럼 3월 2일부터는 열심히 써야지...ㅡㅡ;;
반응형
반응형
그럼 일단 프로젝트를 만들고 시작합시다 >_<
(저 번 시간에 First one 이래놓고.. Fisrst one 이라고 만들었었네요...ㅎㅎ)
오 늘은 저작권이 왠지 근질근질 해지는 강의입니다...ㅠㅠ
 
 
우 선 오늘의 첫번째 예제입니다.
예 제는 http://classroomm.com/objective-c/에 서 무료로 볼 수 있으니 저작권에 걸리지는 않겠죠 ~_~
 
 
(분 명히 조금 다르니까.. 괜찮을거야...)
 
 
실 행 결과입니다. 분수를 처리하는 거랍니다.
그 런데, 분수를 아주 많이 저장해야 한다면, 이런건 귀찮겠죠 ~_~
 
그 래서 다음과 같은 방법으로 클래스를 정의해봅시다.
 
오 늘의 두번째 예제~
 
 
열 심히 치시구요..~_~
(이 번 강의는 왠지 저작권이 위배되는 기분... 근데 이 책 예제가 좋아서리..)
(다 음부터는 그냥 제가 예제를 만들어봐야겠네요...)
 
실 행결과입니다.
 
그 럼 이제, 분석을 시작해봐요 >_<
우 선 가장 먼저 나오는
@interface..!!
@interface 부분은 클래스를 새로 정의합니다.
 
치 시다보면 아래와 같이 뜰겁니다. Tab키를 눌러서 왔다갔다 할 수 있어요.
 
@interface 클래스의 이름 : 슈퍼클래스(부모클래스의 이름)
{
         변수
}
메 소드
@end
 입니다. C++을 공부해보셨다면 쉽게 이해가 되실 겁니다 ~_~
메 소드가 그냥 클래스 함수죠.
 
 "부모클래스가 뭔가요?"-"나중에요."
 
변 수는 그냥 일반적으로 하던데로 하시면 되구요.
메 소드정의가 조금 다릅니다.
-(○○) ○○ : (○○) ○○ : (○○) ○○........ 이런 형태인데요.
 
다 음과 같습니다.
" 메소드형은 뭔가요??"
3 강에서 언급했듯이 메소드는 인스턴스 메소드와 클래스 메소드로 나뉘는데요.
"-" 면 인스턴스 메소드
"+" 면 클래스 메소드입니다. 나중에 보도록 해요 ~_~
 
void mother(int m);과 비슷한데요.
공 통점과 차이점을 잘 알아두시면 쉽게 이해가 되실 수 있을 겁니다.
 
다 음은 @implementation 부분..!
클 래스의 이름과 메소드를 구현합니다.
기 본 형태는 아래와 같습니다.
 
 
C++ 에서와 비슷합니다만 약간 다른점이 있죠 ~_~
 
... 뭘 설명하지...ㅡㅡ;;
넘 어갑니다.(대충대충...아니구.. 그냥)
 
깊 고 자세하게 알고 싶으시면, 책을 구매하세요 ~_~
(저 작권에서 벗어나고 싶은 욕망이 부글부글)
 
(이 런 캡쳐에 마우스가 ㅠㅠ)
 
메 인함수 부분입니다. 오늘의 하이라이트.
Fraction *myFraction; 으로 Fraction 객체를 생성했습니다.
자 동차 공장에서 자동차가 만들어진거죠 ~_~
 
myFraction=[Fraction alloc];
객 체에 메모리를 할당합니다. 나중에 자세히 알아보구요.
"allocate" 입니다. 메모리를 할당하고, 전체 변수를 0으로 초기화 합니다.
 
myFraction=[myFraction init]
"initialize" 초기화 해 줍니다.
 
위 에서 봤던 것을 그냥 한줄에
Fraction *myFraction=[[Fraction alloc] init]; 하면 됩니다.
전 시간에 말한 것 처럼 [주어 동사]의 형태입니다. >_<
 
그 리고 나서, 메소드를 이용해 멤버변수에 접근해 1과 3을 대입하고
show 메소드를 실행시켜 출력합니다.
 
마 지막으로 아까 myFraction객체에게 메모리를 주었으니, 토해내게 하고 프로그램이 종료됩니다.
 
뭐, 딱히 설명할 것이 많지는 않은 것 같아요.(그래서 캡쳐수가 10장이구나....;;)
그 럼 오늘은 여기서 끝 >_< 다음 시간에 뵈요.
오 늘 오브젝티브C 강의를 3개나 올렸으니... 내일은 일이 바빠 쉬겠습니다...ㅎㅎ;;
이 러고 또 저녁에 쓰고 있을듯..!
블 로그 접속자가 65명이나 ~_~
뭐, 많다고 할 수는 없겠지만. 저에게는 많다고 느껴지네요...ㅎㅎ;
(문 제라면 공부하러 들어온 것이냐 하는 것이지...)
보 시면 제발 리플좀 주세요 ㅠ_ㅠ
반응형
반응형

옴마나, 오늘 하루 접속자가 50명이래... >_< 내일 통계가 두근두근 거리겠지만

기대가 크면 실망도 크겠지...OTL

 

어쨌거나 오늘 ObjectiveC 강의 시작합니다~!

오늘 강의는 그림이 한장도 없어 재미가 없을 수 있습니다만, 꼭 알아두고 가세요~

 

이번 강의는 아주 간단한 질문을 해결함으로써 강의를 시작하고, 마치겠습니다 ~_~

 

왜 그 많은 이름 중에 Objective-C라는 이름이 붙었을까요.

Objective 가 뭘까요.

objective 1. 목적, 목표   2. 대물렌즈   3. 객관적인

오브젝티브. 목적, 목표, 객관적인 어쩌구 저쩌구

 

일단 저의 슬픈이야기 부터...흑흑

"아이폰 나왔다...!!" [ ] 차타고 손잡고 아이폰 어플은 만듭세~

"음... 뭐 야, 윈도우에서 안 돌아가는 프로그램으로 짜는거임 ~_~ ?"

"음... 뭥... Objective C는 뭐야, C++, OOP랑 같은거 아닌가...?"

"그냥 아이폰 프로그래밍 바로 시작해버리지 뭐 ~_~"

하고 책을 샀다가 다음날 ObjectiveC 공부 시작...ㅡㅡ

 

"뭐가 슬픈건가요?"

.... 그냥요 한마디 해봤어요.

OOP, Object Oriented Programming 객체 지향프로그래밍의 Object입니다.

객체지향적인 C라는 뜻입니다. ObjectiveC 그럼 문제 해결했으니 끝.... 이 아니구

 

Object : 객체가 뭐지를 알아봐야겠죠 >_<

오늘 강의에서는 아쉽게도, 매킨토시를 키지 않습니다 ~_~ 책을 정리해서쓸게요 ㅎㅎ

(제가 이론을 설명할 실력이 아닌 관계로 ㅋ)

 

객체지향프로그 래밍에 대해 하기 전에, 그 반대적인 절차지향 프로그래밍에 대해 알아봅시다.

C에서는 프로그램을 개발할 때  세가지 처리 패턴이 있는데요.

1. 순차처리 : 시간 흐름 순서대로 처리

2. 조건처리 : 특정 조건에 따라 서로다른 처리

3. 재귀처리 : 동일한 처리를 반복해서 처리

이렇게 3가지 입니다.

절차지향프로그 래밍에서는 프로그램개발을,

[기능도출→데 이터형식 수집→조합]의 방식으로 진행하였습니다.

절차지향에서는 프로그래밍이란 "기능을 어떻게 조합하느냐"에 대한 것입니다.

기능이 프로그램개발의 첫째단계가 되어, 기능을 바꿔야하는 시점에서는 프로그램을 처음부터 다시 제작해야 하는 충격적 시나리오가 벌어졌습니다. ~_~

 

그래서 나온것이 "객체지향프로그래밍"입니다.

"객체"란 "다른것과 구분해서 인식할 수 있는 어떤 대상"을 의미합니다.

라지만 그냥 "어떤 것"정도로 생각합니시다.

객체지향에서 프로그래밍이란 "어떤것이 있고, 그것에 취하고 싶은 행동을 시키는 활동"입니다.

 

[Programming in Objective-C 2.0] 이라는 책에 쉽게 설명이 되어 있어서 인용하겠습니다.

오브젝티브씨를 공부하신다면 한 권있으면 좋은 책인 것 같습니다.

API공부한다 면 [API 정복]을 소유하면 좋은 것 처럼

(이렇게 적었으니 저작권으로 신고는 하지 않겠지.... 좋은 책이에요. 한빛미디어에서 나온건 조금 그런듯)

 

일상에서의 예를 들어, 집에있는 자동차는 "객체"이고, 객체는 여러분이 소유를 하고 있습니다.

아무런 차를 소유하는 것도 아니고, 어딘가에서 생산되어 [서울 ○ ○○○○]이라는 번호판이 붙은 특정한 차를 소유하고 있겠죠. 이 차를 우리는 "인스턴스"라고 합니다. 자동차는 "클래스"이구요. 새로운 차를 찍어낼 때마다 새로운 인스턴스가 생성이되고, 각 자동차는 인스턴스라고 부릅니다.

 

인스턴스=객체

 

자동차는 여러가지 특징이 있을 수 있지요 ~_~

형태, 색상, 커버색상등등 그런 특징이 있을 수 있습니다.

그리고 그 자동차에 취할 수 있는 행동이 있습니다.

"운전한다." "기름을 채운다." "세차한다." "수리한다." 등등 있겠죠.

그리고 옆집에 사는 김모씨의 자동차도 같은 행동을 할 수 있을 겁니다.

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

그럼 계속 설명을 합시다.

클래스로 부터 나온것을 인스턴스라고 하고

인스턴스가 수행하는 행동을 "메서드"라고 합니다.

메서드는 클래스인스턴스나 클래스 자체에 적용이 됩니다.

 

"운전한다." "기름을 채운다." "세차한다." "수리한다."처럼

자신이 소유한 자동차에게 영향을 주는 것을 인스턴스 메서드라고 합니다.

그럼 클래스 메서드는, 클래스에 영향을 주는 거겠죠????

 

공장에서 자동차라는 클래스에서 인스턴스들이 마구마구 찍혀나오고 있는 광경.JPG

(요즘 ~~.JPG많이 하더군요 ㅎㅎ)

 

같은 공장에서 나온 자동차라도 소유자의 행위에 따라 각각 조금씩 다른 특성을 지니게 될 것입니다.

인트턴스는 공장에서 찍혀질 때나온 "초기특징"뿐만 아니라 "현재특징"도 가지고 있으며

이 특징들은 동적으로 변할 수 있습니다.

 

객체에 메소드를 적용하면(무슨 행위를 한다는 뜻이죠.)

객체의 "상태"에 영향을 끼치게 됩니다.

예로 "기름을 채운다."라는 행위를 하면 기름통에 기름이 차겠죠 ~_~

 

각 객체는 자신만 접근 가능한 정보를 포함합니다.

예로, "운전한다." 인데 옆차 핸들 돌리고 엑셀 밟았다고, 우리 차가 나가지는 않잖습니까 ㅎㅎ

이런걸 private 멤버라고 하는데, 나중에 알아보도록 합시다 ㅎㅎ

 

클래스나 인스턴스에 행동을 수행하도록 할때는 '메시지'를 보낸다고 합니다.

그리고 메시지를 받는 쪽을 "리시버(수신자)"라고 하구요.

 

다음 강의에 나올 건데요. 사용되는 문법입니다.

[주어 동사]

[클래스 메소드]

[인스턴스 메소드]

[리시버 메시지]

오늘 강의는 여기서 마치구요. 오늘 강의 하나 더 올라갑니다~!

(앗.. 오늘 새벽에 썼으니까... 3개구나)

 


반응형

'Mobile > Object-C' 카테고리의 다른 글

Objective C 5강 - 연습  (0) 2010.10.01
ObjectiveC 4강 - 객체 예제  (0) 2010.10.01
ObjectiveC 2강 - 첫번째 예제 + NSLog  (0) 2010.10.01
ObjectiveC 1강 - ObjectiveC시작하기  (0) 2010.10.01
ObjectiveC 0강 - Xcode설치  (0) 2010.10.01
반응형

~_~ 에구야, 이 새벽에 내가 잠안자고 뭐하는 건지...

아마도 오브젝티브C강좌가 C강좌 추월할 것만 같은 느낌이 두근두근

(제가 당장 필요한게 오브젝티브 C라... 음 >_< 뭐, 보는 사람도 없는데 내 맘대루 하지 ㅋㅋ)

 

C언어가 약간은 되어있다는 전제를 하고 할게요 ~_~

 

그럼 첫번째 예제부터 시작합시다 >_<

 

 

이거시 보이려나... 당연히 안 보이겠군..ㅡㅡ

(아악 >_< 그럼 나 이제부터 강의할때 윈도우에서 한번 치고 맥에서 한번치고 2번 쳐야하는거..!?)

 

#import<Foundation/Foundation.h>

 

int main(int argc, const char * argv[]){

NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];

//insert code here...

NSLog(@"Hello, World!");

[pool drain];

return 0;

}

오타가 있다면 제발 찾아주심...

일단 Xcode로 프로젝트를 생성하면 가장 처음에 자동으로 생성되는 예제구요.

분석을 시작해 봅시다. >_<

 

C언어와 비슷하면서도 약간 다른 측면이 있습니다.

 

그럼 첫줄

#import<Foundation/Foundation.h>

입니다. #include와 같은 내용입니다. <foundation/Foundation.h>를 포함합니다.

거의 대부분이 다 박혀있는 헤더파일 입니다.

 

 int main(int argc, const char * argv[]){

두번째 줄이죠 >_<

C언어에서의 int main()과 같습니다.

뒤에 써있는 인수가 무엇을 뜻하는지는 나중에 알아보도록하구요, 계속 나가봅시다~

 

 NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];

자동릴리즈풀입니다. 여기서의 풀은 메모리 풀을 뜻하는 것 같아요. ㅎㅎ

메모리 풀이란, 특정크기의 메모리 블럭들을 모아둔 장소입니다.

메모리를 요청하면 블럭을 하나씩 주는 곳이죠.

하지만, 메모리도 한계가 있는 관계로 블럭을 다시 돌려줘야 합니다.

그냥 "풀"이니까 수영장(프로그램)에 물(메모리)을 퍼준다는 기분으로 생각합시다. >_<

NS 란 NextStep의 줄임말인데, 개발툴킷이라는데, 그냥 넘어가구요 그냥 궁금하실 것 같아서요.;;

이것도 뒤로 넘기도록 합시다...(다넘어가...ㅡㅡ;;)

 

NSLog(@"Hello, World!");

어쨌거나, 오늘의 포인트..! C언어의 printf()와 같은 녀석입니다.

모든 프로그래밍 언어의 첫번째 예제는 이 "출력"을 위한거죠

이름도 상당히 직관적이요. 걍 Log, NS의 의미는 앞에서 했구요~

printf("Hello, World!"); 와 같이

NSLog(@"Hello, World!"); 인데요. 다 같은데 딱 한가지 "@" 이 골뱅이 님께서 다르십니다. >_<

"~~"이런 것을, C스타일의 스트링상수 라고 하구요

@"~"이런 것을, NS스타일의 스트링 상수하고 합니다.

우리는 그냥 C를 하는 것이아니니, 이제 Xcode에서 작성하는 모든 문자열은 @"~~"을 사용합시다.

 

[pool drain];

그 다음줄 입니다. 아까 앞에서 메모리를 할당했으니 빼줘야겠죠??

아까 수영장(프로그램)에 물(메모리)를 넣었는데, 다 놀았으니 이제 물을 빼줘야하니

 

drain 1. 물을 빼내다   2. (액체를) 따라 내다   3. (술 등을 다 마셔서 잔을) 비우다

 

해줍니다. 인터넷을 돌아다니다 어떤 분이 [주어 동사]로 설명하시는걸 봤는데요.

와우, 아주 좋은 설명인 것 같아요 ㅎㅎ

 

return 0;

그리고 리턴해주며 프로그램을 종료합니다.

실행 결과인데요.

마지막 줄을 보면. "프로그램이 끝났으영, 0이라는 상태값을 가지고"

라고 되어있는데, 0을 리턴해줬기 때문입니다.

관례적으로 0이 리턴되었다는 것은 "잘 해결 되었다."라는 뜻입니다.

 

근데 뭐

1로 쓴다고 충격적인 일이 발생하거나 하지는 않습니다.

"뒤에 (gdb)라고 되어있는데요?!"

그건 방금 실행시킨거라 그래요...ㅎㅎ

 

어쨌거나 오늘 알아볼것은 "출력"입니다.

"지금 시작하는 건가요?"

네, 지금부터 시작입니다. 앞은 수박 겉 햝기... 햝짝햝짝

 

 NSLog, 완전히 printf()함수와 같은 녀석입니다.

즉, printf("나의 나이 : %d", 20); 이런것도 당연히 되는거죠 >_<

근데 다른점이라면 %d가 아니라 %i라는것..!

 

(앗.. 새벽2시다...)

 

 

그럼 우리가 C에서 했던 것처럼 기본적인 일도 할 수 있겠죠??

어차피 이름부터 ObjectiveC니까, C입니다 >_<

 

 

죄송해여여러분... 차마 또 치기는 손이 후덜덜 하네요...

 

 

실행 결과 입니다.

 

C에서 배우던 일반적인 \n 도 사용이 되었습니다.

 

참고로 stdio.h 임포트 시키면 printf도 사용이 가능합니다. ㅎㅎ

"아니 그럼 왜 NSLog따위를..!"

이렇게 생각하시면, 그냥 C 쓰시구요. 그냥 뭘 새로 걍 배워봅시다.

 

근데, NSLog쓸때와 다른점이 있어요.

감지 하셨나요?!

제가 지금 이글을 쓰고 있는게 2010년 2월 22일 오전 2시 13분이라는 정보가 나오지 않습니다.

(흑흑, 낮잠을 잤더니 잠이 안와 ㅠㅠ)

 

 

 

그럼 오늘은 여기까지 하구요. 내일뵈요.

어제 1강 쓰고 오늘 2강 썼으니까, 내일 3강 쓰면 되겠네요.

아, 책은 아래 두권 병행해서 진행하구요.

 

저작권을 지켜야 하는 관계로,

일단 오픈소스 코드는 최대한 활용하도록 하구요.

(왼쪽의 책은 완전 오픈, 오른쪽의 책도 완전 오픈이니 상관 없겠군여)

이 Objective-C강의는

[위의 두권 + 인터넷을 돌아다니며 보는 좋은 설명 + 나의 손과 머리]를 이용해서 진행이되구요.

끝나는 순간 바로 아이폰 프로그래밍 강좌 올립니다.

음.. 음..... 얼마 안 걸릴 것 같아요.

기본적인 C언어가 되어있다는 가정하에 진행하는거니까요 ㅎㅎ

 

책 어떤거 추천하냐고 물으면(묻지도 않겠지만)

왼쪽꺼요. 훨씬 자세합니다. 오른쪽꺼는 뭐, 기초책이 아닙니다. ~_~

오른쪽 책을 사게된 경위는 제 싸이에 오시면 알겠지만 에구구... 실수였음 ㅋ

 

그럼 빠이~!

반응형

'Mobile > Object-C' 카테고리의 다른 글

ObjectiveC 4강 - 객체 예제  (0) 2010.10.01
ObjectiveC 3강 - 왜 ObjectiveC라고 하나요.  (0) 2010.10.01
ObjectiveC 1강 - ObjectiveC시작하기  (0) 2010.10.01
ObjectiveC 0강 - Xcode설치  (0) 2010.10.01
Objective-C Tutorial  (0) 2010.09.14
반응형

C언어를 배우신 분은 오브젝티브C 볼 필요 없이 바로 아이폰 나가셔도 댑니다 ~_~

오브젝티브씨 맥미니 없을때 쓴 글이라 굉장히 느려터져서

짜증나서 대충대충 썼답니담 ㅇㅅㅇ...

 

강의를 어떻게 나갈지 고민 디게 많이 했는데...

방금 1강 올렸다가 지우고 다시써요 ㅋ

 

맥이라는 것 자체가 윈도우와 약간... 많이 다른 감이 있어서 적응이 안되니까.

그냥 완전 처음부터 할게요. 그래도 C언어랑 비교하면서 할거니까,

C언어가 기초정도는 되어 있어야 이해가 될듯...ㅎㅎ;;

  

그럼 시작합시다 ~_~

 

우선 프로젝트를 생성해봅시다.

처음 Xcode를 실행하면 아래와 같이 뜹니다.

만약에 이거 뜨기 싫으시다면 아래쪽에 체크되어 있는걸 꺼주시면 됩니다.

 

 

프로젝트를 만드는 곳에 들어왔습니다.

Command Line Tool 에서 Foundation을 선택해주세요.

 

 

다른걸 선택하시면 그것에 해당하는 프로그래밍을 진행할 수 있습니다.

뭐, 우리는 지금 Foundation 을 선택합시다 >_<

 

 

Choose를 누르면 아래와 같이 뜹니다.

이름을 설정하구요.

우선, 첫번째 OBJ-C 프로그램이니까, "First one"으로 하겠습니다.

 

 

그리고 폴더를 지정해 주시구요~

 

 

저는 폴더를 하나 더 만들었습니다.

그리구 거기에 저장 >_<

 

 

그럼 아래와 같이 뜹니다.

Visual Studio와 많이 다른 모습을 보여주고 있습니다. @_@

저두 적응이 잘 안됩니다 ~_~

 

 

First one.m 이 을 누르시면

아래와 같이 작성이 이미 되어있습니다.

오늘 강의에서는 그냥 프로젝트의 생성과 실행방법만 알아보는거니, 분석은 하지 않겠습니다.

 

 

Build and Run을 누르시면 갑자기 뭐가 변했는데 뭐가 갑자기 사라집니다. ~_~

Visual Studio처럼 Ctrl+F5도 없고 참 난감한 상황...>_<

 

 

위의 Xcode 메뉴에서 Run

Console을 클릭해주세요 >_<

 

 

그럼 아래와 같이 콘솔창이 뜨고, "Hello, World!"가 실행이 된 것을 볼 수 있습니다.

 

 

 

어쨌거나, 오늘은 간단히 Xcode의 사용법에 대해 배웠습니다. >_<

그럼 다음강의부터 제대로 시작합니다~!

반응형

'Mobile > Object-C' 카테고리의 다른 글

ObjectiveC 4강 - 객체 예제  (0) 2010.10.01
ObjectiveC 3강 - 왜 ObjectiveC라고 하나요.  (0) 2010.10.01
ObjectiveC 2강 - 첫번째 예제 + NSLog  (0) 2010.10.01
ObjectiveC 0강 - Xcode설치  (0) 2010.10.01
Objective-C Tutorial  (0) 2010.09.14
반응형

허허... objective C 책이나 인터넷들을 보니.. Xcode의 기본 설치를 전제로 하더군요.

그래서, 저는 Xcode의 설치부터 시작하겠습니다 >_<

 

우선 저는 해킨토시를 사용합니다. 맥북이나 미니맥 너무 비싸영....

(윈도우 테마를 바꿔보았습니다. C 강의에서 분홍색 테두리로 바꿨다고 말했는데 ㅎㅎ)

(단지 취향일뿐..ㅡㅡ)

 

 해킨토시를 실행합니다.

 


 

저도 할줄 몰라서

명동 갔다가 프리스비(맞나...?) 맥 매장가서 "Xcode"기본내장 아닌지 물어봤는데, 모르더군요.

그래서 아는분한테 여쭈었더니, CD에 있다는 군요. ㅋ

[CD]를 누르고, [선택설치]-[Xcode.mpkg]를 선택합니다.

 


 

여타 윈도우 프로그램들과 같이 다음다음 설치설치 눌러주면 됩니다 ㅋ

 


 

열심히 설치를 합니다.

 

 

아...Xcode 끄고 하라네..ㅡㅡ(전 설치가 이미 되어있으니까요 ㅋ)

 


 

해서 해서 설치 끝 >_<

 


 

그럼 이제 Xcode를 실행해 봅시다 ㅋ

 


 

아래쪽에 있는 Xcode 버튼을 누릅니다.

윈도우랑 달라 적응이 잘 안되더군요 ..ㅠㅠ 누르면

윗쪽에 줄이 딱 뜹니다. Xcode 하고

File-New Project..

 


 

그럼 아래와 같이 뜹니다.

(저는 아이폰 SDK를 깔았어요 >_<)

 


 

일단, 오늘은 설치강의니까, 여기서 끝내도록 하구요~

다음 강의에 만나요 ㅋ

반응형
반응형
Tristan O’Tierney이 운영하는 Objective-C Tutorial의 한국어 버전을 번역했다. Tristan에게 허가를 구했고, 내가 번역한 파일은 그가 사용할 수 있도록 했다. Objective-C의 문법을 빠르게 그리고 간략하게 잘 설명해서 여러사람에게 도움이 될 것 같아 번역했다.

HTML버전은 http://kjune.com/objc/objective-c-kor.html
원본 사이트 : http://www.otierney.net/objective-c.html.ko


개요


    시작하기

    이 튜토리얼 다운로드

    • 이 가이드에 사용된 소스 코드와 Makefile은 objc.tar.gz에서 다운 받을 수 있다. 이 튜토리얼의 예제들은 Steve Kochan씨가 쓴 Programming in Objective-C에서 인용한 것이다. 더 자세한 정보와 예제가 필요하다면, 이 책을 참조하면 도움이 될 것이다. 이 사이트에서 사용된 예제는 그의 허가를 받고 사용한 것이므로, 다른 곳에 무단 복제를 금지한다.

    환경설정

    • Linux/FreeBSD: GNUStep를 설치
      • GNUStep 어플리케이션을 빌드하기 위해서는 먼저 /usr/GNUstep/System/Makefiles/GNUstep.sh에 있는 GNUstep.sh 스크립트를 실행한다. 경로는 시스템에 따라 다를 수 있다. /usr, 혹은 /usr/lib, 혹은 /usr/local를 찾아볼 것. 만약 사용하는 셀이 csh/tcsh 기반의 쉘이라면, GNUStep.csh를 대신 실행시키면 된다. 이 스크립트를 쉘 설정파일인 .bashrc 이나 .cshrc에 추가하는 것을 추천한다.
    • Mac OS X: XCode설치
    • Windows NT 5.X: 먼저 cygwin 이나 mingw를 설치한 후에 GNUStep을 설치

    머리말

    • 이 튜토리얼은 사용자가 기본적인 C 지식이 있다고 전제하고 설명을 하고 있다. C의 데이터형, 함수, 반환값, 포인터와 기본적인 메모리 관리등이 이에 해당된다. 아직 여기까지 내용을 모른다면, 다음의 책을 참조하길 바란다. The C Programming Language. 이 책은 C언어를 만든 사람들이 만든 바로 그 책이다.
    • 오브젝티브-C는 C의 파생언어여서 C의 많은 기능을 차용받았다. 하지만 C로 부터 오지 않은 다른 부분들도 있다.
    • nil: C/C++ 에서는 NULL이라고 사용하는 데, 오브젝티브-C에서는 nil이라고 한다. 차이점은 nil에게는 메시지를 전달할 수 있다는 점이다. (예를 들면 이런 식으로 [nil message];) 이렇게 해도 괜찮다. 반면 C에서 NULL에게는 이렇게 할 수 없다.
    • BOOL: C에는 공식적인 불린 형이 없다. 사실 오브젝티브-C에서도 공식적인 불린형은 없다. 하지만 불린형은 Foundation classes에 포함이 되어서 (NSObject.h를 임포트 함으로써) 그리고 nil도 역시 이 헤더파일로부터 추가된다. 오브젝티브-C에서의 BOOL은 YES나 NO라는 2개의 모드를 갖는다. (TRUE나 FALSE가 아니다.)
    • #import 대 #include: 위의 hello world 예제에서 눈치챘겠지만, 파일을 포함할 때 #import를 사용한다. #import는 gcc 컴파일러가 지원한다. 다만 #include를 더 선호하기 때문에 덜 사용되게 될 뿐이다. #import는 사용자가 만든 .h파일의 위와 아래에 #ifndef #define #endif 블럭을 붙이는 것과 같은 일을 한다. 이 블럭을 붙이는 건 정말 멍청한 짓이라고 생각하고, 아마 다른 모든 개발자들도 동의할 것이다. 따라서 그냥 #import를 사용하면 된다. 걱정할 필요도 없고, gcc에서 #import를 제거한다고 해도, 다른 오브젝티브-C 개발자들이 그런 일이 생기지 못하게 할 것이다. 공식적으로 애플에서 #import를 자신들의 코드에 사용하니, 만약 #import가 gcc에서 사라진다고 해도, 애플에서는 gcc를 변형한 버전이라도 출시할 것이다.
    • 비록 메시지가 조금 더 특별한 특성을 가지긴 해도, 메소드와 메시지란 단어는 오브젝티브-C에서는 서로 교환 가능한 말이다. 메시지는 동적으로 다른 객체에게 포워딩 될 수 있다. 오브젝티브-C에서 객체의 메시지를 호출한다는 것은 객체가 그 메시지를 구현한 다는 것을 의미하는 것이 아니다. 단지 객체가 메시지가 전달되었을 때 어떻게 반응해야 하는 지를 안다는 뜻이다. 그 방식은 직접 구현을 하거나 혹은 처리방법을 아는 다른 객체에 메시지를 포워딩하는 방식을 사용할 수 있다.

    hello world 만들기

    • hello.m
      1. #import <stdio.h>  
      2.   
      3. int main( int argc, const char *argv[] ) {  
      4. printf( "hello world\n" );  
      5. return 0;  
      6. }  
    • 결과
      hello world
    • 오브젝티브-C에서는 #include 대신에 #import를 사용한다.
    • 오브젝티브-C의 기본 확장자는 .m이다.

클래스 만들기

    인터페이스 @interface

    • 예제의 출처: “Programming in 오브젝티브-C,” Copyright © 2004 출판사 Sams Publishing. 허가 받고 사용함
    • Fraction.h
      1. #import <Foundation/NSObject.h>  
      2.   
      3. @interface Fraction: NSObject {  
      4. int numerator;  
      5. int denominator;  
      6. }  
      7.   
      8. -(void) print;  
      9. -(void) setNumerator: (int) n;  
      10. -(void) setDenominator: (int) d;  
      11. -(int) numerator;  
      12. -(int) denominator;  
      13. @end  
    • NSObject: NeXTStep Object의 줄임말. 이제는 OpenStep으로 이름이 바꿔서 의미가 맞지 않긴 하다.
    • 상속, 다형성, 그리고 다른 객체 지향 프로그래밍의 기능들은 Class: Parent와 같은 형태로 표현하면 된다. 위의 예제에서는 Fraction: NSObject 부분이다.
    • 인스턴스 변수들은 @interface Class: Parent { …. }의 안쪽으로 들어간다.
    • 아직 접근 레벨이 정해져 있지 않다. (protected, public, private). 기본은 protected이다. 접근 셋팅하는 법은 뒤에 더 다루겠다.
    • 멤버 함수 뒤에는 인스턴스 메소드가 나온다. 포멧은 scope (returnType) methodName: (parameter1Type) parameter1Name;과 같다.
      • 스코프(scope)는 매스드가 클래스에서 사용하는지 인스턴스에서 사용하는 지를 판별한다. 인스턴스에서 사용하는 메소드는 -를, 클래스에서 사용하는 메소드는 +로 시작한다.
    • 인터페이스는 @end로 끝난다.

    @implementation

    • 예제의 출처: “Programming in 오브젝티브-C,” Copyright © 2004 출판사 Sams Publishing. 허가 받고 사용함
    • Fraction.m
      1. #import "Fraction.h"  
      2. #import <stdio.h>  
      3.   
      4. @implementation Fraction  
      5. -(void) print {  
      6. printf( "%i/%i", numerator, denominator );  
      7. }  
      8.   
      9. -(void) setNumerator: (int) n {  
      10. numerator = n;  
      11. }  
      12.   
      13. -(void) setDenominator: (int) d {  
      14. denominator = d;  
      15. }  
      16.   
      17. -(int) denominator {  
      18. return denominator;  
      19. }  
      20.   
      21. -(int) numerator {  
      22. return numerator;  
      23. }  
      24. @end  
    • 클래스의 구현부분은 @implementation ClassName 으로 시작하고, @end으로 끝난다.
    • 모든 정의된 메소드들은 인터페이스에서 정의된 것과 유사한 형태로 구현된다.

    모두 합하기

    • 예제의 출처: “Programming in 오브젝티브-C,” Copyright © 2004 출판사 Sams Publishing. 허가 받고 사용함
    • main.m
      1. #import <stdio.h>  
      2. #import "Fraction.h"  
      3.   
      4. int main( int argc, const char *argv[] ) {  
      5. // create a new instance  
      6. Fraction *frac = [[Fraction alloc] init];  
      7.   
      8. // set the values  
      9. [frac setNumerator: 1];  
      10. [frac setDenominator: 3];  
      11.   
      12. // print it  
      13. printf( "The fraction is: " );  
      14. [frac print];  
      15. printf( "\n" );  
      16.   
      17. // free memory  
      18. [frac release];  
      19.   
      20. return 0;  
      21. }  
    • 결과
      The fraction is: 1/3
    • Fraction *frac = [[Fraction alloc] init];
      • 이 한 줄에는 몇 가지 중요한 것들이 있다.
      • 오브젝티브-C에서 메소드는 [object method]와 같은 형태로 호출된다. C++에서는 object->method() 와 같은 형태로 호출되는 것과 유사하다.
      • 오브젝티브-C에는 값 타입이 없다. 다시 말해 C++처럼 Fraction frac; frac.print(); 이런 식으로 코딩하지 않는 다는 뜻이다. 오브젝티브-C에서는 반드시 객체를 포인터를 통해서 다뤄야 한다.
      • 이 한 줄에서 실제로는 두 가지 일이 일어난다: [Fraction alloc]은 Fracion 클래스의 alloc 메소드를 호출한다. 이 것은 메모리를 할당하는 것과 유사하다. 이 단계에서 메모리 할당이 일어난다.
      • [object init]은 객체 안에 있는 여러 변수들의 값을 초기화하는 생성자 호출이다. 이 메소드는 [Fraction alloc]에 의해서 반환된 인스턴스가 호출한다. 보통 이 과정은 다음과 같은 형태로 한 줄로 이뤄진다. Object* var = [[Object alloc]init];
    • [frac setNumerator: 1]은 간단하다. frac객체의 setNumerator 함수를 호출하면서 인자 1을 전달한다.
    • 다른 C의 변종들과 마찬가지로, 메모리를 해제하는 구조가 있다. 여기에서는 release를 통해서 처리되었는데, 이는 NSObject에서 상속 받은 것이다. 이에 대해서는 뒤에서 더 자세히 다루겠다.

세부적인 내용들

    매개변수를 여러 개 갖는 경우

    • 지금까지는 매개변수가 여러 개인 함수는 나오지 않았다. 처음에 보면 방식이 직관적이지 않다는 생각이 드는데, 이 것은 스몰토크(Smalltalk)로 부터 차용해온 것이다.
    • 예제의 출처: “Programming in 오브젝티브-C,” Copyright © 2004 출판사 Sams Publishing. 허가 받고 사용함
    • Fraction.h
      1. ...  
      2. -(void) setNumerator: (int) n andDenominator: (int) d;  
      3. ...  
    • Fraction.m
      1. ...  
      2. -(void) setNumerator: (int) n andDenominator: (int) d {  
      3. numerator = n;  
      4. denominator = d;  
      5. }  
      6. ...  
    • main.m
      1. #import <stdio.h>  
      2. #import "Fraction.h"  
      3.   
      4. int main( int argc, const char *argv[] ) {  
      5. // create a new instance  
      6. Fraction *frac = [[Fraction alloc] init];  
      7. Fraction *frac2 = [[Fraction alloc] init];  
      8.   
      9. // set the values  
      10. [frac setNumerator: 1];  
      11. [frac setDenominator: 3];  
      12.   
      13. // combined set  
      14. [frac2 setNumerator: 1 andDenominator: 5];  
      15.   
      16. // print it  
      17. printf( "The fraction is: " );  
      18. [frac print];  
      19. printf( "\n" );  
      20.   
      21. // print it  
      22. printf( "Fraction 2 is: " );  
      23. [frac2 print];  
      24. printf( "\n" );  
      25.   
      26. // free memory  
      27. [frac release];  
      28. [frac2 release];  
      29.   
      30. return 0;  
      31. }  
    • 결과
      The fraction is: 1/3
      Fraction 2 is: 1/5
    • 메소드는 실제로 setNumerator:andDenominator:를 호출했다.
    • 더 많은 인자를 전달하고자 할 때는 두번째 인자를 전달하는 것과 같은 방식으로 하면 된다. method:label1:label2:label3: 그런 다음 호출할 때에는 [obj method: param1 label1: param2 label2: param3 label3: param4]식으로 하면 된다.
    • 레이블은 써도 되고 안써도 된다. 메소드 이름을 method:::라고 해도 된다. 레이블 이름을 쓰지 않으면 이렇게 된다. 그리고 a: 를 인자를 구분하기 위해서 사용한다. 하지만, 이 방식을 추천하진 않는다.

    생성자

    • 예제의 출처: “Programming in 오브젝티브-C,” Copyright © 2004 출판사 Sams Publishing. 허가 받고 사용함
    • Fraction.h
      1. ...  
      2. -(Fraction*) initWithNumerator: (int) n denominator: (int) d;  
      3. ...  
    • Fraction.m
      1. ...  
      2. -(Fraction*) initWithNumerator: (int) n denominator: (int) d {  
      3. self = [super init];  
      4.   
      5. if ( self ) {  
      6. [self setNumerator: n andDenominator: d];  
      7. }  
      8.   
      9. return self;  
      10. }  
      11. ...  
    • main.m
      1. #import <stdio.h>  
      2. #import "Fraction.h"  
      3.   
      4. int main( int argc, const char *argv[] ) {  
      5. // create a new instance  
      6. Fraction *frac = [[Fraction alloc] init];  
      7. Fraction *frac2 = [[Fraction alloc] init];  
      8. Fraction *frac3 = [[Fraction alloc] initWithNumerator: 3 denominator: 10];  
      9.   
      10. // set the values  
      11. [frac setNumerator: 1];  
      12. [frac setDenominator: 3];  
      13.   
      14. // combined set  
      15. [frac2 setNumerator: 1 andDenominator: 5];  
      16.   
      17. // print it  
      18. printf( "The fraction is: " );  
      19. [frac print];  
      20. printf( "\n" );  
      21.   
      22. printf( "Fraction 2 is: " );  
      23. [frac2 print];  
      24. printf( "\n" );  
      25.   
      26. printf( "Fraction 3 is: " );  
      27. [frac3 print];  
      28. printf( "\n" );  
      29.   
      30. // free memory  
      31. [frac release];  
      32. [frac2 release];  
      33. [frac3 release];  
      34.   
      35. return 0;  
      36. }  
    • 결과
      The fraction is: 1/3
      Fraction 2 is: 1/5
      Fraction 3 is: 3/10
    • @interface선언은 다른 함수들과 동일하다.
    • @implementation에 새로운 키워드 super가 등장했다.
      • 자바와 마찬가지로 오브젝티브-C에는 오직 한 개의 부모 클래스만을 가진다.
      • 부모의 생성자를 호출하기 위해서는 [super init]을 호출한다. 적절하게 상속을 하기 위해서 반드시 해야 한다.
      • 여기에 self라는 또 다른 키워드가 등장한다. self는 자기 자신에 대한 인스턴스를 가리킨다. self는 자바나 C++에서의 this와 유사하다.
    • if ( self ) 라고 쓰는 것은 if ( self != nil ) 와 동일하다. 부모 클래스의 생성자로부터 성공적으로 새 객체를 생성해서 받아왔다는 것을 보장하기 위해서 사용한 것이다. 오브젝티브-C에서의 nil은 C/C++의 NULL과 같다. NSObject를 포함함으로써 추가되었다.
    • 값들을 초기화 한 후에는 return self;를 통해서 자기 자신의 객체를 반환해야 한다.
    • 초기 생성자는 -(id) init; 이다.
    • 오브젝티브-C에서의 생성자는 단순한 “init” 메소드이다. C++이나 자바에서처럼 특별한 생성자가 있는 것은 아니다.

    접근 권한

    • 기본 권한은 @protected이다.
    • 자바에서는 개별 메소드와 변수 앞에 public/private/protect라고 표시를 한다. 오브젝티브-C는 C++과 유사한 방식이다.
    • Access.h
      1. #import <Foundation/NSObject.h>  
      2.   
      3. @interface Access: NSObject {  
      4. @public  
      5. int publicVar;  
      6. @private  
      7. int privateVar;  
      8. int privateVar2;  
      9. @protected  
      10. int protectedVar;  
      11. }  
      12. @end  
    • Access.m
      1. #import "Access.h"  
      2.   
      3. @implementation Access  
      4. @end  
    • main.m
      1. #import "Access.h"  
      2. #import <stdio.h>  
      3.   
      4. int main( int argc, const char *argv[] ) {  
      5. Access *a = [[Access alloc] init];  
      6.   
      7. // works  
      8. a->publicVar = 5;  
      9. printf( "public var: %i\n", a->publicVar );  
      10.   
      11. // doesn't compile  
      12. //a->privateVar = 10;  
      13. //printf( "private var: %i\n", a->privateVar );  
      14.   
      15. [a release];  
      16. return 0;  
      17. }  
    • 결과
      public var: 5
    • 위에서 본 바와 같이 C++에서는 private: [list of vars] public: [list of vars]와 같이 표시하는 것을 여기에서는 @private, @protected, 등등으로 표시한다.

    클래스 수준 접근성

    • 종종 클래스 수준에서 변수와 함수를 조절할 수 있는 것이 필요할 때가 있다. 예를 들어, 객체가 인스턴스화 된 횟수를 추적하고자 할 때와 같은 경우이다.
    • ClassA.h
      1. #import <Foundation/NSObject.h>  
      2.   
      3. static int count;  
      4.   
      5. @interface ClassA: NSObject  
      6. +(int) initCount;  
      7. +(void) initialize;  
      8. @end  
    • ClassA.m
      1. #import "ClassA.h"  
      2.   
      3. @implementation ClassA  
      4. -(id) init {  
      5. self = [super init];  
      6. count++;  
      7. return self;  
      8. }  
      9.   
      10. +(int) initCount {  
      11. return count;  
      12. }  
      13.   
      14. +(void) initialize {  
      15. count = 0;  
      16. }  
      17. @end  
    • main.m
      1. #import "ClassA.h"  
      2. #import <stdio.h>  
      3.   
      4. int main( int argc, const char *argv[] ) {  
      5. ClassA *c1 = [[ClassA alloc] init];  
      6. ClassA *c2 = [[ClassA alloc] init];  
      7.   
      8. // print count  
      9. printf( "ClassA count: %i\n", [ClassA initCount] );  
      10.   
      11. ClassA *c3 = [[ClassA alloc] init];  
      12.   
      13. // print count again  
      14. printf( "ClassA count: %i\n", [ClassA initCount] );  
      15.   
      16. [c1 release];  
      17. [c2 release];  
      18. [c3 release];  
      19.   
      20. return 0;  
      21. }  
    • 결과
      ClassA count: 2
      ClassA count: 3
    • static int count = 0; 이렇게 클래스 변수를 선언한다. 이 방법이 변수를 보관하는 가장 좋은 방법은 아니다. 자바에서 구현하는 것이 조금 더 좋은 해결책으로 생각되지만, 이 방법도 된다.
    • +(int) initCount; 이 함수가 실제로 객수를 반환한다. 눈여겨볼 차이점이 하나가 있는데 형 앞에 -를 쓴 대신 +를 사용했다. +는 클래스 레벨 함수라는 뜻이다.
    • 클래스 레벨의 변수를 접근 하는 방식은 일반 멤버 변수를 접근 하는 방식과 동일하다. ClassA의 생성자에 있는 count++를 보면 된다.
    • +(void) initialize 메소드는 오브젝티브-C가 프로그램을 시작할 때 호출된다. 그리고 이 모든 클래스에서 호출된다. 따라서 이 예제의 count와 같은 클래스 레벨의 변수를 초기화 하기에 좋은 위치이다.

    예외처리

    • 참고: 예외 처리는 오직 맥 OS X 10.3에서 지원됩니다.
    • 예제의 출처: “Programming in 오브젝티브-C,” Copyright © 2004 출판사 Sams Publishing. 허가 받고 사용함
    • CupWarningException.h
      1. #import <Foundation/NSException.h>  
      2.   
      3. @interface CupWarningException: NSException  
      4. @end  
    • CupWarningException.m
      1. #import "CupWarningException.h"  
      2.   
      3. @implementation CupWarningException  
      4. @end  
    • CupOverflowException.h
      1. #import <Foundation/NSException.h>  
      2.   
      3. @interface CupOverflowException: NSException  
      4. @end  
    • CupOverflowException.m
      1. #import "CupOverflowException.h"  
      2.   
      3. @implementation CupOverflowException  
      4. @end  
    • Cup.h
      1. #import <Foundation/NSObject.h>  
      2.   
      3. @interface Cup: NSObject {  
      4. int level;  
      5. }  
      6.   
      7. -(int) level;  
      8. -(void) setLevel: (int) l;  
      9. -(void) fill;  
      10. -(void) empty;  
      11. -(void) print;  
      12. @end  
    • Cup.m
      1. #import "Cup.h"  
      2. #import "CupOverflowException.h"  
      3. #import "CupWarningException.h"  
      4. #import <Foundation/NSException.h>  
      5. #import <Foundation/NSString.h>  
      6.   
      7. @implementation Cup  
      8. -(id) init {  
      9. self = [super init];  
      10.   
      11. if ( self ) {  
      12. [self setLevel: 0];  
      13. }  
      14.   
      15. return self;  
      16. }  
      17.   
      18. -(int) level {  
      19. return level;  
      20. }  
      21.   
      22. -(void) setLevel: (int) l {  
      23. level = l;  
      24.   
      25. if ( level > 100 ) {  
      26. // throw overflow  
      27. NSException *e = [CupOverflowException  
      28. exceptionWithName: @"CupOverflowException"  
      29. reason: @"The level is above 100"  
      30. userInfo: nil];  
      31. @throw e;  
      32. else if ( level >= 50 ) {  
      33. // throw warning  
      34. NSException *e = [CupWarningException  
      35. exceptionWithName: @"CupWarningException"  
      36. reason: @"The level is above or at 50"  
      37. userInfo: nil];  
      38. @throw e;  
      39. else if ( level < 0 ) {  
      40. // throw exception  
      41. NSException *e = [NSException  
      42. exceptionWithName: @"CupUnderflowException"  
      43. reason: @"The level is below 0"  
      44. userInfo: nil];  
      45. @throw e;  
      46. }  
      47. }  
      48.   
      49. -(void) fill {  
      50. [self setLevel: level + 10];  
      51. }  
      52.   
      53. -(void) empty {  
      54. [self setLevel: level - 10];  
      55. }  
      56.   
      57. -(void) print {  
      58. printf( "Cup level is: %i\n", level );  
      59. }  
      60. @end  
    • main.m
      1. #import "Cup.h"  
      2. #import "CupOverflowException.h"  
      3. #import "CupWarningException.h"  
      4. #import <Foundation/NSString.h>  
      5. #import <Foundation/NSException.h>  
      6. #import <Foundation/NSAutoreleasePool.h>  
      7. #import <stdio.h>  
      8.   
      9. int main( int argc, const char *argv[] ) {  
      10. NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];  
      11. Cup *cup = [[Cup alloc] init];  
      12. int i;  
      13.   
      14. // this will work  
      15. for ( i = 0; i < 4; i++ ) {  
      16. [cup fill];  
      17. [cup print];  
      18. }  
      19.   
      20. // this will throw 예외처리  
      21. for ( i = 0; i < 7; i++ ) {  
      22. @try {  
      23. [cup fill];  
      24. } @catch ( CupWarningException *e ) {  
      25. printf( "%s: ", [[e name] cString] );  
      26. } @catch ( CupOverflowException *e ) {  
      27. printf( "%s: ", [[e name] cString] );  
      28. } @finally {  
      29. [cup print];  
      30. }  
      31. }  
      32.   
      33. // throw a generic exception  
      34. @try {  
      35. [cup setLevel: -1];  
      36. } @catch ( NSException *e ) {  
      37. printf( "%s: %s\n", [[e name] cString], [[e reason] cString] );  
      38. }  
      39.   
      40. // free memory  
      41. [cup release];  
      42. [pool release];  
      43. }  
    • 결과
      Cup level is: 10
      Cup level is: 20
      Cup level is: 30
      Cup level is: 40
      CupWarningException: Cup level is: 50
      CupWarningException: Cup level is: 60
      CupWarningException: Cup level is: 70
      CupWarningException: Cup level is: 80
      CupWarningException: Cup level is: 90
      CupWarningException: Cup level is: 100
      CupOverflowException: Cup level is: 110
      CupUnderflowException: The level is below 0
    • NSAutoreleasePool은 메모리 관리 클래스이다. 지금은 일단 넘어가자.
    • 전달 받은 예외를 처리하기 위해서 NSException을 확장할 필요는 없다. 간단히 id를 사용하면 된다. @catch ( id e ) { … }
    • 마지막 부분에 finally 블럭이 있다. 자바와 유사하게 작동하는데, finally 블럭에 있는 구문은 반드시 호출되게 되어있다.
    • Cub.m에 있는 문자열 @”CupOverflowException”은 NSString 상수 객체이다. 오브젝티브-C에서의 @표시는 언어의 확장을 의미한다. C스트링은 C나 C++과 유사하다. 문자열 상수이고 모두 char*로 만들어져 있다.

상속, 다형성, 그리고 다른 객체 지향 프로그래밍의 기능들

    id 형

    • 오브젝티브-C에는 id라는 특별한 형이 있다. 이것은 여러가지 면에서 void*와 유사하게 사용된다. 하지만 반드시 객체에 대해서만 사용된다. 오브젝티브-C는 객체의 메소드를 호출 하는 방식에 있어서 자바나 C++과 다른데, 이 때에 객체의 타입을 알 필요가 없다. 단지 메소드만 있으면 된다. 이것이 오브젝티브-C에서 메시지를 전달하는 방식으로 간주된다.
    • 예제의 출처: “Programming in 오브젝티브-C,” Copyright © 2004 출판사 Sams Publishing. 허가 받고 사용함
    • Fraction.h
      1. #import <Foundation/NSObject.h>  
      2.   
      3. @interface Fraction: NSObject {  
      4. int numerator;  
      5. int denominator;  
      6. }  
      7.   
      8. -(Fraction*) initWithNumerator: (int) n denominator: (int) d;  
      9. -(void) print;  
      10. -(void) setNumerator: (int) d;  
      11. -(void) setDenominator: (int) d;  
      12. -(void) setNumerator: (int) n andDenominator: (int) d;  
      13. -(int) numerator;  
      14. -(int) denominator;  
      15. @end  
    • Fraction.m
      1. #import "Fraction.h"  
      2. #import <stdio.h>  
      3.   
      4. @implementation Fraction  
      5. -(Fraction*) initWithNumerator: (int) n denominator: (int) d {  
      6. self = [super init];  
      7.   
      8. if ( self ) {  
      9. [self setNumerator: n andDenominator: d];  
      10. }  
      11.   
      12. return self;  
      13. }  
      14.   
      15. -(void) print {  
      16. printf( "%i / %i", numerator, denominator );  
      17. }  
      18.   
      19. -(void) setNumerator: (int) n {  
      20. numerator = n;  
      21. }  
      22.   
      23. -(void) setDenominator: (int) d {  
      24. denominator = d;  
      25. }  
      26.   
      27. -(void) setNumerator: (int) n andDenominator: (int) d {  
      28. numerator = n;  
      29. denominator = d;  
      30. }  
      31.   
      32. -(int) denominator {  
      33. return denominator;  
      34. }  
      35.   
      36. -(int) numerator {  
      37. return numerator;  
      38. }  
      39. @end  
    • Complex.h
      1. #import <Foundation/NSObject.h>  
      2.   
      3. @interface Complex: NSObject {  
      4. double real;  
      5. double imaginary;  
      6. }  
      7.   
      8. -(Complex*) initWithReal: (double) r andImaginary: (double) i;  
      9. -(void) setReal: (double) r;  
      10. -(void) setImaginary: (double) i;  
      11. -(void) setReal: (double) r andImaginary: (double) i;  
      12. -(double) real;  
      13. -(double) imaginary;  
      14. -(void) print;  
      15.   
      16. @end  
    • Complex.m
      1. #import "Complex.h"  
      2. #import <stdio.h>  
      3.   
      4. @implementation Complex  
      5. -(Complex*) initWithReal: (double) r andImaginary: (double) i {  
      6. self = [super init];  
      7.   
      8. if ( self ) {  
      9. [self setReal: r andImaginary: i];  
      10. }  
      11.   
      12. return self;  
      13. }  
      14.   
      15. -(void) setReal: (double) r {  
      16. real = r;  
      17. }  
      18.   
      19. -(void) setImaginary: (double) i {  
      20. imaginary = i;  
      21. }  
      22.   
      23. -(void) setReal: (double) r andImaginary: (double) i {  
      24. real = r;  
      25. imaginary = i;  
      26. }  
      27.   
      28. -(double) real {  
      29. return real;  
      30. }  
      31.   
      32. -(double) imaginary {  
      33. return imaginary;  
      34. }  
      35.   
      36. -(void) print {  
      37. printf( "%_f + %_fi", real, imaginary );  
      38. }  
      39.   
      40. @end  
    • main.m
      1. #import <stdio.h>  
      2. #import "Fraction.h"  
      3. #import "Complex.h"  
      4.   
      5. int main( int argc, const char *argv[] ) {  
      6. // create a new instance  
      7. Fraction *frac = [[Fraction alloc] initWithNumerator: 1 denominator: 10];  
      8. Complex *comp = [[Complex alloc] initWithReal: 10 andImaginary: 15];  
      9. id number;  
      10.   
      11. // print fraction  
      12. number = frac;  
      13. printf( "The fraction is: " );  
      14. [number print];  
      15. printf( "\n" );  
      16.   
      17. // print complex  
      18. number = comp;  
      19. printf( "The complex number is: " );  
      20. [number print];  
      21. printf( "\n" );  
      22.   
      23. // free memory  
      24. [frac release];  
      25. [comp release];  
      26.   
      27. return 0;  
      28. }  
    • 결과
      The fraction is: 1 / 10
      The complex number is: 10.000000 + 15.000000i
    • 이런 식의 동적인 형 연결을 통해서 여러가지 이득이 있다. 어떤 함수를 호출하기 위해서 그 객체의 형을 반드시 알 필요는 없다. 만약 객체가 메시지에 반응한다면, 그 메소드를 호출할 것이다. 그렇기 때문에 지저분한 캐스팅 문제가 오브젝티브-C에서는 발생하지 않는 것이다. 자바에서는 .intValue() 라는 함수를 호출하려면 먼저 캐스팅을 해야하고, 그 뒤에 메소드를 호출해야 하는 것과는 대조적이다.

    상속, 다형성, 그리고 다른 객체 지향 프로그래밍의 기능들

    • 예제의 출처: “Programming in 오브젝티브-C,” Copyright © 2004 출판사 Sams Publishing. 허가 받고 사용함
    • Rectangle.h
      1. #import <Foundation/NSObject.h>  
      2.   
      3. @interface Rectangle: NSObject {  
      4. int width;  
      5. int height;  
      6. }  
      7.   
      8. -(Rectangle*) initWithWidth: (int) w height: (int) h;  
      9. -(void) setWidth: (int) w;  
      10. -(void) setHeight: (int) h;  
      11. -(void) setWidth: (int) w height: (int) h;  
      12. -(int) width;  
      13. -(int) height;  
      14. -(void) print;  
      15. @end  
    • Rectangle.m
      1. #import "Rectangle.h"  
      2. #import <stdio.h>  
      3.   
      4. @implementation Rectangle  
      5. -(Rectangle*) initWithWidth: (int) w height: (int) h {  
      6. self = [super init];  
      7.   
      8. if ( self ) {  
      9. [self setWidth: w height: h];  
      10. }  
      11.   
      12. return self;  
      13. }  
      14.   
      15. -(void) setWidth: (int) w {  
      16. width = w;  
      17. }  
      18.   
      19. -(void) setHeight: (int) h {  
      20. height = h;  
      21. }  
      22.   
      23. -(void) setWidth: (int) w height: (int) h {  
      24. width = w;  
      25. height = h;  
      26. }  
      27.   
      28. -(int) width {  
      29. return width;  
      30. }  
      31.   
      32. -(int) height {  
      33. return  height;  
      34. }  
      35.   
      36. -(void) print {  
      37. printf( "width = %i, height = %i", width, height );  
      38. }  
      39. @end  
    • Square.h
      1. #import "Rectangle.h"  
      2.   
      3. @interface Square: Rectangle  
      4. -(Square*) initWithSize: (int) s;  
      5. -(void) setSize: (int) s;  
      6. -(int) size;  
      7. @end  
    • Square.m
      1. #import "Square.h"  
      2.   
      3. @implementation Square  
      4. -(Square*) initWithSize: (int) s {  
      5. self = [super init];  
      6.   
      7. if ( self ) {  
      8. [self setSize: s];  
      9. }  
      10.   
      11. return self;  
      12. }  
      13.   
      14. -(void) setSize: (int) s {  
      15. width = s;  
      16. height = s;  
      17. }  
      18.   
      19. -(int) size {  
      20. return width;  
      21. }  
      22.   
      23. -(void) setWidth: (int) w {  
      24. [self setSize: w];  
      25. }  
      26.   
      27. -(void) setHeight: (int) h {  
      28. [self setSize: h];  
      29. }  
      30. @end  
    • main.m
      1. #import "Square.h"  
      2. #import "Rectangle.h"  
      3. #import <stdio.h>  
      4.   
      5. int main( int argc, const char *argv[] ) {  
      6. Rectangle *rec = [[Rectangle alloc] initWithWidth: 10 height: 20];  
      7. Square *sq = [[Square alloc] initWithSize: 15];  
      8.   
      9. // print em  
      10. printf( "Rectangle: " );  
      11. [rec print];  
      12. printf( "\n" );  
      13.   
      14. printf( "Square: " );  
      15. [sq print];  
      16. printf( "\n" );  
      17.   
      18. // update square  
      19. [sq setWidth: 20];  
      20. printf( "Square after change: " );  
      21. [sq print];  
      22. printf( "\n" );  
      23.   
      24. // free memory  
      25. [rec release];  
      26. [sq release];  
      27.   
      28. return 0;  
      29. }  
    • 결과
      Rectangle: width = 10, height = 20
      Square: width = 15, height = 15
      Square after change: width = 20, height = 20
    • 오브젝티브-C에서 상속, 다형성, 그리고 다른 객체 지향 프로그래밍의 기능들은 자바와 유사하다. 상위 클래스를 확장하려고 한다면, (단일 상속만 가능하다) 하위 클래스에서 상위 클래스에 있는 메소드와 같은 이름으로 메소드를 선언하고, 해당 내용을 구현을 함으로서 메소드 오버로딩을 할 수 있다. C++처럼 가상 테이블로 장난칠 필요가 없다.
    • 한 가지 짚고 넘어갈 문제가 있다. 만약에 다음과 같이 사각형 객체의 생성자를 출하면 어떻게 될것인가? Square *sq = [[Square alloc] initWithWidth: 10 height: 15]. 답은 이 문장은 컴파일 에러가 날것이다. rectangle 클래스 생성자가 반환하는 값이 Rectangle*이지 Square*가 아니기 때문에 이 문장은 에러가 나는 것이다. 이런 문제가 생길 경우에 id 변수를 사용하는 것이 좋다. 만약 하위 클래스에서 상위 클래스의 생성자를 사용하길 원한다면 Rectangle*의 반환 형을 id로 바꾸면 된다.

    동적 형

    • 오브젝티브-C에서는 동적형에서 사용할 수 있는 몇 가지 중요한 메소드가 있다.
      • -(BOOL) isKindOfClass: classObj 이 객체가 ClassObj의 멤버이거나 상속을 받은 하위클래스인지?
        -(BOOL) isMemberOfClass: classObj 이 객체가 classObj의 멤버인지
        -(BOOL) respondsToSelector: selector 이 객체가 selector란 이름의 메소드를 가지고 있는지?
        +(BOOL) instancesRespondToSelector: selector 이 클래스로 만들어진 객체가 지정된 셀렉터에 반응할 능력이 있는지?
        -(id) performSelector: selector 객체의 지정된 셀렉터를 실행한다.
    • NSObject로 부터 상속받은 모든 객체는 클래스 객체를 반환하는 메소드를 가지고 있다. 자바의 getClass() 메소드와 유사한데, 이 클래스 객체는 위의 메소드들을 사용할 수 있다.
    • 오브젝티브-C에서 셀렉터는 메시지를 표현하기 위해서 사용된다. 셀렉터를 만드는 문법은 다음 예를 보면 된다.
    • 예제의 출처: “Programming in 오브젝티브-C,” Copyright © 2004 출판사 Sams Publishing. 허가 받고 사용함
    • main.m
      1. #import "Square.h"  
      2. #import "Rectangle.h"  
      3. #import <stdio.h>  
      4.   
      5. int main( int argc, const char *argv[] ) {  
      6. Rectangle *rec = [[Rectangle alloc] initWithWidth: 10 height: 20];  
      7. Square *sq = [[Square alloc] initWithSize: 15];  
      8.   
      9. // isMemberOfClass  
      10.   
      11. // true  
      12. if ( [sq isMemberOfClass: [Square class]] == YES ) {  
      13. printf( "square is a member of square class\n" );  
      14. }  
      15.   
      16. // false  
      17. if ( [sq isMemberOfClass: [Rectangle class]] == YES ) {  
      18. printf( "square is a member of rectangle class\n" );  
      19. }  
      20.   
      21. // false  
      22. if ( [sq isMemberOfClass: [NSObject class]] == YES ) {  
      23. printf( "square is a member of object class\n" );  
      24. }  
      25.   
      26. // isKindOfClass  
      27.   
      28. // true  
      29. if ( [sq isKindOfClass: [Square class]] == YES ) {  
      30. printf( "square is a kind of square class\n" );  
      31. }  
      32.   
      33. // true  
      34. if ( [sq isKindOfClass: [Rectangle class]] == YES ) {  
      35. printf( "square is a kind of rectangle class\n" );  
      36. }  
      37.   
      38. // true  
      39. if ( [sq isKindOfClass: [NSObject class]] == YES ) {  
      40. printf( "square is a kind of object class\n" );  
      41. }  
      42.   
      43. // respondsToSelector  
      44.   
      45. // true  
      46. if ( [sq respondsToSelector: @selector( setSize: )] == YES ) {  
      47. printf( "square responds to setSize: method\n" );  
      48. }  
      49.   
      50. // false  
      51. if ( [sq respondsToSelector: @selector( nonExistant )] == YES ) {  
      52. printf( "square responds to nonExistant method\n" );  
      53. }  
      54.   
      55. // true  
      56. if ( [Square respondsToSelector: @selector( alloc )] == YES ) {  
      57. printf( "square class responds to alloc method\n" );  
      58. }  
      59.   
      60. // instancesRespondToSelector  
      61.   
      62. // false  
      63. if ( [Rectangle instancesRespondToSelector: @selector( setSize: )] == YES ) {  
      64. printf( "rectangle instance responds to setSize: method\n" );  
      65. }  
      66.   
      67. // true  
      68. if ( [Square instancesRespondToSelector: @selector( setSize: )] == YES ) {  
      69. printf( "square instance responds to setSize: method\n" );  
      70. }  
      71.   
      72. // free memory  
      73. [rec release];  
      74. [sq release];  
      75.   
      76. return 0;  
      77. }  
    • 결과
      square is a member of square class
      square is a kind of square class
      square is a kind of rectangle class
      square is a kind of object class
      square responds to setSize: method
      square class responds to alloc method
      square instance responds to setSize: method

    카테고리

    • 클래스에 메소드를 추가하고 싶을 때에는 보통 클래스를 확장시키면 된다. 이 방법이 여의치 않을 때가 있을 수 있는데 특히 소스코드가 없다던지 할 경우가 있을 것이다. 카테고리는 이미 존재하는 클래스를 확장시키지 않고 원하는 기능을 추가할 수 있도록 해준다. 유사한 기능이 루비(Ruby)에 있다.
    • 예제의 출처: “Programming in 오브젝티브-C,” Copyright © 2004 출판사 Sams Publishing. 허가 받고 사용함
    • FractionMath.h
      1. #import "Fraction.h"  
      2.   
      3. @interface Fraction (Math)  
      4. -(Fraction*) add: (Fraction*) f;  
      5. -(Fraction*) mul: (Fraction*) f;  
      6. -(Fraction*) div: (Fraction*) f;  
      7. -(Fraction*) sub: (Fraction*) f;  
      8. @end  
    • FractionMath.m
      1. #import "FractionMath.h"  
      2.   
      3. @implementation Fraction (Math)  
      4. -(Fraction*) add: (Fraction*) f {  
      5. return [[Fraction alloc] initWithNumerator: numerator * [f denominator] +  
      6. denominator * [f numerator]  
      7. denominator: denominator * [f denominator]];  
      8. }  
      9.   
      10. -(Fraction*) mul: (Fraction*) f {  
      11. return [[Fraction alloc] initWithNumerator: numerator * [f numerator]  
      12. denominator: denominator * [f denominator]];  
      13.   
      14. }  
      15.   
      16. -(Fraction*) div: (Fraction*) f {  
      17. return [[Fraction alloc] initWithNumerator: numerator * [f denominator]  
      18. denominator: denominator * [f numerator]];  
      19. }  
      20.   
      21. -(Fraction*) sub: (Fraction*) f {  
      22. return [[Fraction alloc] initWithNumerator: numerator * [f denominator] -  
      23. denominator * [f numerator]  
      24. denominator: denominator * [f denominator]];  
      25. }  
      26. @end  
    • main.m
      1. #import <stdio.h>  
      2. #import "Fraction.h"  
      3. #import "FractionMath.h"  
      4.   
      5. int main( int argc, const char *argv[] ) {  
      6. // create a new instance  
      7. Fraction *frac1 = [[Fraction alloc] initWithNumerator: 1 denominator: 3];  
      8. Fraction *frac2 = [[Fraction alloc] initWithNumerator: 2 denominator: 5];  
      9. Fraction *frac3 = [frac1 mul: frac2];  
      10.   
      11. // print it  
      12. [frac1 print];  
      13. printf( " * " );  
      14. [frac2 print];  
      15. printf( " = " );  
      16. [frac3 print];  
      17. printf( "\n" );  
      18.   
      19. // free memory  
      20. [frac1 release];  
      21. [frac2 release];  
      22. [frac3 release];  
      23.   
      24. return 0;  
      25. }  
    • 결과
      1/3 * 2/5 = 2/15
    • 마법은 바로 2개의 @implementation과 @interface에 있다. @interface Fraction (Math) 과 @implementation Fraction (Math).
    • 같은 이름으로는 오직 한 개만의 카테고리가 존재한다. 다른 카테고리는 다른 유일한 이름으로 만들어야 한다.
    • 카테고리에는 인스턴스 변수를 추가할 수 없다.
    • 카테고리는 private 메소드를 만들 때 유용한다. 오브젝티브-C에는 자바에서 처럼 private/protected/public 메소드를 구분하는 명확한 개념이 없기 때문에, 감추고 싶은 메소드를 만들 때에는 카테고리를 이용해서 이러한 기능들을 숨길 수 있다. 이 방법은 클래스의 private 메소드들을 클래스 헤더파일(.h)로 빼서 소스파일(*.m)으로 옮기는 것이다. 다음이 방금 이야기 한 것의 간단한 예이다.
    • MyClass.h
      1. #import <Foundation/NSObject.h>  
      2.   
      3. @interface MyClass: NSObject  
      4. -(void) publicMethod;  
      5. @end  
    • MyClass.m
      1. #import "MyClass.h"  
      2. #import <stdio.h>  
      3.   
      4. @implementation MyClass  
      5. -(void) publicMethod {  
      6. printf( "public method\n" );  
      7. }  
      8. @end  
      9.   
      10. // private methods  
      11. @interface MyClass (Private)  
      12. -(void) privateMethod;  
      13. @end  
      14.   
      15. @implementation MyClass (Private)  
      16. -(void) privateMethod {  
      17. printf( "private method\n" );  
      18. }  
      19. @end  
    • main.m
      1. #import "MyClass.h"  
      2.   
      3. int main( int argc, const char *argv[] ) {  
      4. MyClass *obj = [[MyClass alloc] init];  
      5.   
      6. // this compiles  
      7. [obj publicMethod];  
      8.   
      9. // this throws errors when compiling  
      10. //[obj privateMethod];  
      11.   
      12. // free memory  
      13. [obj release];  
      14.   
      15. return 0;  
      16. }  
    • 결과
      public method

    포즈

    • 포즈는 카테고리와 유사하지만 좀 더 복잡하다. 포즈를 사용하면 클래스를 확장할 수도 있고, 하위 클래스를 포즈함으로써 상위 클래스를 전역적으로 바꿔치기 할 수 있다. 예를 들면, NSArray를 확장한 NSArrayChild 클래스를 만들었다고 하자. 만약 NSArrayChild 클래스를 NSArray를 포즈하도록 했다면, 당신의 코드 전체에서 자동으로 NSArray대신에 NSArrayChild를 사용할 것이다.
    • 예제의 출처: “Programming in 오브젝티브-C,” Copyright © 2004 출판사 Sams Publishing. 허가 받고 사용함
    • FractionB.h
      1. #import "Fraction.h"  
      2.   
      3. @interface FractionB: Fraction  
      4. -(void) print;  
      5. @end  
    • FractionB.m
      1. #import "FractionB.h"  
      2. #import <stdio.h>  
      3.   
      4. @implementation FractionB  
      5. -(void) print {  
      6. printf( "(%i/%i)", numerator, denominator );  
      7. }  
      8. @end  
    • main.m
      1. #import <stdio.h>  
      2. #import "Fraction.h"  
      3. #import "FractionB.h"  
      4.   
      5. int main( int argc, const char *argv[] ) {  
      6. Fraction *frac = [[Fraction alloc] initWithNumerator: 3 denominator: 10];  
      7.   
      8. // print it  
      9. printf( "The fraction is: " );  
      10. [frac print];  
      11. printf( "\n" );  
      12.   
      13. // make FractionB pose as Fraction  
      14. [FractionB poseAsClass: [Fraction class]];  
      15.   
      16. Fraction *frac2 = [[Fraction alloc] initWithNumerator: 3 denominator: 10];  
      17.   
      18. // print it  
      19. printf( "The fraction is: " );  
      20. [frac2 print];  
      21. printf( "\n" );  
      22.   
      23. // free memory  
      24. [frac release];  
      25. [frac2 release];  
      26.   
      27. return 0;  
      28. }  
    • 결과
      The fraction is: 3/10
      The fraction is: (3/10)
    • 첫번째 fraction에서 출력한 결과는 3/10이지만 두번째 출력은 (3/10)이다. 이 값은 FractionB로 부터 나왔다.
    • 메소드 poseAsClass는 NSObject의 일부분이다. 이 메소드가 하위 클래스를 상위 클래스인 것처럼 행사할 수 있게 해준다.

    프로토콜

    • 오브젝티브-C에서의 프로토콜은 자바의 인터페이스나 C++의 순수가상함수와 동일하다.
    • 예제의 출처: “Programming in 오브젝티브-C,” Copyright © 2004 출판사 Sams Publishing. 허가 받고 사용함
    • Printing.h
      1. @protocol Printing  
      2. -(void) print;  
      3. @end  
    • Fraction.h
      1. #import <Foundation/NSObject.h>  
      2. #import "Printing.h"  
      3.   
      4. @interface Fraction: NSObject <Printing, NSCopying> {  
      5. int numerator;  
      6. int denominator;  
      7. }  
      8.   
      9. -(Fraction*) initWithNumerator: (int) n denominator: (int) d;  
      10. -(void) setNumerator: (int) d;  
      11. -(void) setDenominator: (int) d;  
      12. -(void) setNumerator: (int) n andDenominator: (int) d;  
      13. -(int) numerator;  
      14. -(int) denominator;  
      15. @end  
    • Fraction.m
      1. #import "Fraction.h"  
      2. #import <stdio.h>  
      3.   
      4. @implementation Fraction  
      5. -(Fraction*) initWithNumerator: (int) n denominator: (int) d {  
      6. self = [super init];  
      7.   
      8. if ( self ) {  
      9. [self setNumerator: n andDenominator: d];  
      10. }  
      11.   
      12. return self;  
      13. }  
      14.   
      15. -(void) print {  
      16. printf( "%i/%i", numerator, denominator );  
      17. }  
      18.   
      19. -(void) setNumerator: (int) n {  
      20. numerator = n;  
      21. }  
      22.   
      23. -(void) setDenominator: (int) d {  
      24. denominator = d;  
      25. }  
      26.   
      27. -(void) setNumerator: (int) n andDenominator: (int) d {  
      28. numerator = n;  
      29. denominator = d;  
      30. }  
      31.   
      32. -(int) denominator {  
      33. return denominator;  
      34. }  
      35.   
      36. -(int) numerator {  
      37. return numerator;  
      38. }  
      39.   
      40. -(Fraction*) copyWithZone: (NSZone*) zone {  
      41. return [[Fraction allocWithZone: zone] initWithNumerator: numerator  
      42. denominator: denominator];  
      43. }  
      44. @end  
    • Complex.h
      1. #import <Foundation/NSObject.h>  
      2. #import "Printing.h"  
      3.   
      4. @interface Complex: NSObject <Printing> {  
      5. double real;  
      6. double imaginary;  
      7. }  
      8.   
      9. -(Complex*) initWithReal: (double) r andImaginary: (double) i;  
      10. -(void) setReal: (double) r;  
      11. -(void) setImaginary: (double) i;  
      12. -(void) setReal: (double) r andImaginary: (double) i;  
      13. -(double) real;  
      14. -(double) imaginary;  
      15. @end  
    • Complex.m
      1. #import "Complex.h"  
      2. #import <stdio.h>  
      3.   
      4. @implementation Complex  
      5. -(Complex*) initWithReal: (double) r andImaginary: (double) i {  
      6. self = [super init];  
      7.   
      8. if ( self ) {  
      9. [self setReal: r andImaginary: i];  
      10. }  
      11.   
      12. return self;  
      13. }  
      14.   
      15. -(void) setReal: (double) r {  
      16. real = r;  
      17. }  
      18.   
      19. -(void) setImaginary: (double) i {  
      20. imaginary = i;  
      21. }  
      22.   
      23. -(void) setReal: (double) r andImaginary: (double) i {  
      24. real = r;  
      25. imaginary = i;  
      26. }  
      27.   
      28. -(double) real {  
      29. return real;  
      30. }  
      31.   
      32. -(double) imaginary {  
      33. return imaginary;  
      34. }  
      35.   
      36. -(void) print {  
      37. printf( "%_f + %_fi", real, imaginary );  
      38. }  
      39. @end  
    • main.m
      1. #import <stdio.h>  
      2. #import "Fraction.h"  
      3. #import "Complex.h"  
      4.   
      5. int main( int argc, const char *argv[] ) {  
      6. // create a new instance  
      7. Fraction *frac = [[Fraction alloc] initWithNumerator: 3 denominator: 10];  
      8. Complex *comp = [[Complex alloc] initWithReal: 5 andImaginary: 15];  
      9. id <Printing> printable;  
      10. id <NSCopying, Printing> copyPrintable;  
      11.   
      12. // print it  
      13. printable = frac;  
      14. printf( "The fraction is: " );  
      15. [printable print];  
      16. printf( "\n" );  
      17.   
      18. // print complex  
      19. printable = comp;  
      20. printf( "The complex number is: " );  
      21. [printable print];  
      22. printf( "\n" );  
      23.   
      24. // this compiles because Fraction comforms to both Printing and NSCopyable  
      25. copyPrintable = frac;  
      26.   
      27. // this doesn't compile because Complex only conforms to Printing  
      28. //copyPrintable = comp;  
      29.   
      30. // test conformance  
      31.   
      32. // true  
      33. if ( [frac conformsToProtocol: @protocol( NSCopying )] == YES ) {  
      34. printf( "Fraction conforms to NSCopying\n" );  
      35. }  
      36.   
      37. // false  
      38. if ( [comp conformsToProtocol: @protocol( NSCopying )] == YES ) {  
      39. printf( "Complex conforms to NSCopying\n" );  
      40. }  
      41.   
      42. // free memory  
      43. [frac release];  
      44. [comp release];  
      45.   
      46. return 0;  
      47. }  
    • 결과
      The fraction is: 3/10
      The complex number is: 5.000000 + 15.000000i
      Fraction conforms to NSCopying
    • 프로토콜 문법은 간단하다. @protocol ProtocolName (methods you must implement) @end 이라고 작성하면 된다
    • 프로토콜에 따르게 하기 위해서는 따르게 하고자 하는 프로토콜을 <> 안에 넣고 쉼표로 이 것들을 구분한다. 예: @interface SomeClass <Protocol1, Protocol2, Protocol3>
    • 프로토콜이 사용하기 위해서 구현되어야 하는 메소드들은 헤더파일에 메소드의 리스트에 있을 필요는 없다. 위에서 보는 바와 마찬가지로 Complex.h에는 -(void) print에 대한 정의가 없다. 하지만 protocol에 부합되기 위해서 구현이 되어야 한다.
    • 오브젝티브-C’의 인터페이스 시스템에서 한가지 특이한 점은 사용자가 어떻게 형을 지정하는가 하는 점이다. 자바나 C++에서라면 다음과 같이 Printing *someVar = ( Printing * ) frac; 명시적으로 형을 표현했을 것이지만, 오브젝티브-C에서는 id형과 프로토콜을 사용해서 다음과 같이 id <Printing> var = frac; 표현한다. 이것이 여러 개의 프로토콜에서 필요로 하는 형을 단 하나의 변수를 사용해서 동적으로 명시하도록 해준다. 다음의 예를 보라 id <Printing, NSCopying> var = frac;
    • 객체의 상속을 시험하기 위해 @selector를 사용하는 것과 마찬가지로, 인터페이스의 합치성을 시험하기 위해서 @protocol을 사용할 수 있다. [object conformsToProtocol: @protocol( SomeProtocol )]은 프로토콜과 객체가 규격을 준수하는지의 여부를 BOOL형으로 반환하는 함수이다. 클래스의 경우에도 마찬가지로 사용할 수 있다. [SomeClass conformsToProtocol: @protocol( SomeProtocol )].

메모리 관리

  • 지금까지 오브젝티브-C에서 메모리 관리하는 부분에 대해 자세히 설명을 하지 않았었다. 물론 객체는 dealloc하면 메모리가 해지되겠지만, 객체가 다른 객체로의 포인터를 가지고 있는 경우에는 어떻게 할 것인가? 이런 객체의 메모리를 해제할 때에는 주의를 기울여야 할 것이다. 도한 파운데이션 프레임워크에서는 클래스를 만들 때 어떻게 메모리를 관리하는 지에 대해서도 알아야 할 것이다. 이런 것에 대한 설명을 이제 시작하려고 한다.
  • 주의: 지금까지 작성한 예제들은 모두 적절히 메모리가 관리되었다. 혹시 궁금해할까바.
  • Retain과 Release

    • Retain과 release는 NSObject를 상속받은 모든 객체가 가지고 있는 2개의 메소드이다. 모든 객체는 내부적으로 카운터를 가지고 있어서 객체의 레퍼런스의 개수를 추적하고 있다. 그래서 만약 3개의 레퍼런스를 가지고 있는 경우에는 자기 자신을 dealloc하면 안될 것이다. 만약 0개의 레퍼런스를 가지고 있다면 dealloc해도 될 것이다. [object retain]은 레퍼런스 카운터를 하나 증가시키고 [object release]는 하나 감소시킨다. 만약 [object release]가 호출되어서 카운터가 0에 도달하면 dealloc이 호출된다.
    • Fraction.m
      1. ...  
      2. -(void) dealloc {  
      3. printf( "Deallocing fraction\n" );  
      4. [super dealloc];  
      5. }  
      6. ...  
    • 예제의 출처: “Programming in 오브젝티브-C,” Copyright © 2004 출판사 Sams Publishing. 허가 받고 사용함
    • main.m
      1. #import "Fraction.h"  
      2. #import <stdio.h>  
      3.   
      4. int main( int argc, const char *argv[] ) {  
      5. Fraction *frac1 = [[Fraction alloc] init];  
      6. Fraction *frac2 = [[Fraction alloc] init];  
      7.   
      8. // print current counts  
      9. printf( "Fraction 1 retain count: %i\n", [frac1 retainCount] );  
      10. printf( "Fraction 2 retain count: %i\n", [frac2 retainCount] );  
      11.   
      12. // increment them  
      13. [frac1 retain]; // 2  
      14. [frac1 retain]; // 3  
      15. [frac2 retain]; // 2  
      16.   
      17. // print current counts  
      18. printf( "Fraction 1 retain count: %i\n", [frac1 retainCount] );  
      19. printf( "Fraction 2 retain count: %i\n", [frac2 retainCount] );  
      20.   
      21. // decrement  
      22. [frac1 release]; // 2  
      23. [frac2 release]; // 1  
      24.   
      25. // print current counts  
      26. printf( "Fraction 1 retain count: %i\n", [frac1 retainCount] );  
      27. printf( "Fraction 2 retain count: %i\n", [frac2 retainCount] );  
      28.   
      29. // release them until they dealloc themselves  
      30. [frac1 release]; // 1  
      31. [frac1 release]; // 0  
      32. [frac2 release]; // 0  
      33. }  
    • 결과
      Fraction 1 retain count: 1
      Fraction 2 retain count: 1
      Fraction 1 retain count: 3
      Fraction 2 retain count: 2
      Fraction 1 retain count: 2
      Fraction 2 retain count: 1
      Deallocing fraction
      Deallocing fraction
    • retain 호출이 카운터를 증가시키고, release 호출이 카운터를 감소시킨다. 카운트 자체는 [obj retainCount]를 통해서 얻을 수 있다. 카운터가 0에 도달하면 두 객체 모두 dealloc이 실행되고 둘다 “Deallocing fraction”이란 메시지를 출력하는 것을 볼 수 있다.

    Dealloc

    • 객체가 다른 객체를 포함하고 있는 경우에는 자기 자신을 제거하기 전에 다른 객체도 메모리에서 제거시켜야 한다. 오브젝티브-C를 사용할 때의 다른 좋은 점은 nil에도 메시지를 전달할 수 있기 때문에 객체를 제거할 때 에러 검사를 많이 할 필요가 없다.
    • 예제의 출처: “Programming in 오브젝티브-C,” Copyright © 2004 출판사 Sams Publishing. 허가 받고 사용함
    • AddressCard.h
      1. #import <Foundation/NSObject.h>  
      2. #import <Foundation/NSString.h>  
      3.   
      4. @interface AddressCard: NSObject {  
      5. NSString *first;  
      6. NSString *last;  
      7. NSString *email;  
      8. }  
      9.   
      10. -(AddressCard*) initWithFirst: (NSString*) f  
      11. last: (NSString*) l  
      12. email: (NSString*) e;  
      13. -(NSString*) first;  
      14. -(NSString*) last;  
      15. -(NSString*) email;  
      16. -(void) setFirst: (NSString*) f;  
      17. -(void) setLast: (NSString*) l;  
      18. -(void) setEmail: (NSString*) e;  
      19. -(void) setFirst: (NSString*) f  
      20. last: (NSString*) l  
      21. email: (NSString*) e;  
      22. -(void) setFirst: (NSString*) f last: (NSString*) l;  
      23. -(void) print;  
      24. @end  
    • AddressCard.m
      1. #import "AddressCard.h"  
      2. #import <stdio.h>  
      3.   
      4. @implementation AddressCard  
      5. -(AddressCard*) initWithFirst: (NSString*) f  
      6. last: (NSString*) l  
      7. email: (NSString*) e {  
      8. self = [super init];  
      9.   
      10. if ( self ) {  
      11. [self setFirst: f last: l email: e];  
      12. }  
      13.   
      14. return self;  
      15. }  
      16.   
      17. -(NSString*) first {  
      18. return first;  
      19. }  
      20.   
      21. -(NSString*) last {  
      22. return last;  
      23. }  
      24.   
      25. -(NSString*) email {  
      26. return email;  
      27. }  
      28.   
      29. -(void) setFirst: (NSString*) f {  
      30. [f retain];  
      31. [first release];  
      32. first = f;  
      33. }  
      34.   
      35. -(void) setLast: (NSString*) l {  
      36. [l retain];  
      37. [last release];  
      38. last = l;  
      39. }  
      40.   
      41. -(void) setEmail: (NSString*) e {  
      42. [e retain];  
      43. [email release];  
      44. email = e;  
      45. }  
      46.   
      47. -(void) setFirst: (NSString*) f  
      48. last: (NSString*) l  
      49. email: (NSString*) e {  
      50. [self setFirst: f];  
      51. [self setLast: l];  
      52. [self setEmail: e];  
      53. }  
      54.   
      55. -(void) setFirst: (NSString*) f last: (NSString*) l {  
      56. [self setFirst: f];  
      57. [self setLast: l];  
      58. }  
      59.   
      60. -(void) print {  
      61. printf( "%s %s <%s>", [first cString],  
      62. [last cString],  
      63. [email cString] );  
      64. }  
      65.   
      66. -(void) dealloc {  
      67. [first release];  
      68. [last release];  
      69. [email release];  
      70.   
      71. [super dealloc];  
      72. }  
      73. @end  
    • main.m
      1. #import "AddressCard.h"  
      2. #import <Foundation/NSString.h>  
      3. #import <stdio.h>  
      4.   
      5. int main( int argc, const char *argv[] ) {  
      6. NSString *first =[[NSString alloc] initWithCString: "Tom"];  
      7. NSString *last = [[NSString alloc] initWithCString: "Jones"];  
      8. NSString *email = [[NSString alloc] initWithCString: "tom@jones.com"];  
      9. AddressCard *tom = [[AddressCard alloc] initWithFirst: first  
      10. last: last  
      11. email: email];  
      12.   
      13. // we're done with the strings, so we must dealloc them  
      14. [first release];  
      15. [last release];  
      16. [email release];  
      17.   
      18. // print to show the retain count  
      19. printf( "Retain count: %i\n", [[tom first] retainCount] );  
      20. [tom print];  
      21. printf( "\n" );  
      22.   
      23. // free memory  
      24. [tom release];  
      25.   
      26. return 0;  
      27. }  
    • 결과
      Retain count: 1
      Tom Jones <tom@jones.com>
    • 이 예제의 AddressCard.m을 보면 어떻게 dealloc 메소드를 호출하는 지와 AddressCard 클래스의 멤버 변수들의 메모리를 해제할 때 어떻게 해야 하는 지를 알 수 있다.
    • 각각의 set 메소드에서 일어나는 3동작의 순서가 매우 중요하다. set 함수에 자신의 인자를 넘긴다고 해보자(좀 이상한 예이지만 이런 경우도 있다.) 만약 release를 먼저하고 그 다음에 retain을 한다면 자기 자신을 제거해 버릴 것이다. 따라서 항상 반드시 다음의 순서로 값을 설정하는 것이 중요하다. 1) retain 2) release 3) 값 정하기
    • 보통의 경우에 C 문자열로 변수를 초기하는 경우는 없을 것이다. 왜냐면 C 스트링은 유니코드를 지원하지 않기 때문이다. 다음의 예제에서는 NSAutoreleasePool을 사용하는데, 여기에서 문자열을 사용하고 초기화하는 적절한 방법을 다룰 것이다.
    • 이 방법은 멤버 변수 메모리 관리하는 한 방법에 불과하다. 또 다른 방법으로는 set 메소드 안에서 값을 복사하는 방법이 있다.

    Autorelease Pool

    • NSString과 다른 파운데이션 프레임워크를 이용해서 프로그래밍 할 때 더 유연한 시스템이 필요할 것이다. 이 시스템은 Autolease Pool을 사용한다.
    • 맥 코코아 어플리케이션을 사용할 때, auto release pool은 자동으로 사용 가능하다.
    • 예제의 출처: “Programming in 오브젝티브-C,” Copyright © 2004 출판사 Sams Publishing. 허가 받고 사용함
    • main.m
      1. #import <Foundation/NSString.h>  
      2. #import <Foundation/NSAutoreleasePool.h>  
      3. #import <stdio.h>  
      4.   
      5. int main( int argc, const char *argv[] ) {  
      6. NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];  
      7. NSString *str1 = @"constant string";  
      8. NSString *str2 = [NSString stringWithString: @"string managed by the pool"];  
      9. NSString *str3 = [[NSString alloc] initWithString: @"self managed string"];  
      10.   
      11. // print the strings  
      12. printf( "%s retain count: %x\n", [str1 cString], [str1 retainCount] );  
      13. printf( "%s retain count: %x\n", [str2 cString], [str2 retainCount] );  
      14. printf( "%s retain count: %x\n", [str3 cString], [str3 retainCount] );  
      15.   
      16. // free memory  
      17. [str3 release];  
      18.   
      19. // free pool  
      20. [pool release];  
      21. return 0;  
      22. }  
    • 결과
      constant string retain count: ffffffff
      string managed by the pool retain count: 1
      self managed string retain count: 1
    • 이 예제에서 몇 가지가 눈에 뛸 것이다. 먼저 str1의 카운터가 ffffff이다.
    • 다른 점은 str3만 release 했는데, 이 프로그램에서 메모리 관리는 완벽히 이뤄지고 있다. 그 이유는 첫번째 상수 문자열은 자동으로 autorelease pool에 추가되었고, 다른 문자열은 stringWithString으로 만들어 졌는데, 이 함수는 NSString 클래스에 포함된 문자열을 만들면서 자체적으로 auto release pool에 문자열을 추가한다.
    • 적절한 메모리 관리를 위해서 반드시 기억해야 할 점은, 편의성을 위해 만든 [NSString stringWithString: @"String"]와 같은 함수들은 autorelease pool을 사용한다는 점이다. 반면 [[NSString alloc] initWithString: @”String”]과 같이 직접 메모리를 할당해서 만든 함수들은 메모리 관리를 위해 autorelease pools을 사용하지 않는다는 점이다.
    • 오브젝티브-C에서는 메모리를 관리하는데 2가지 방법이 있다. 1) retain과 release 혹은 2) retain과 release/autorelease.
    • 모든 retain에는 반드시 한 개의 release나 autorealse가 있어야 한다.
    • 다음 예제가 이 내용을 설명하고 있다.
    • 예제의 출처: “Programming in 오브젝티브-C,” Copyright © 2004 출판사 Sams Publishing. 허가 받고 사용함
    • Fraction.h
      1. ...  
      2. +(Fraction*) fractionWithNumerator: (int) n denominator: (int) d;  
      3. ...  
    • Fraction.m
      1. ...  
      2. +(Fraction*) fractionWithNumerator: (int) n denominator: (int) d {  
      3. Fraction *ret = [[Fraction alloc] initWithNumerator: n denominator: d];  
      4. [ret autorelease];  
      5.   
      6. return ret;  
      7. }  
      8. ...  
    • main.m
      1. #import <Foundation/NSAutoreleasePool.h>  
      2. #import "Fraction.h"  
      3. #import <stdio.h>  
      4.   
      5. int main( int argc, const char *argv[] ) {  
      6. NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];  
      7. Fraction *frac1 = [Fraction fractionWithNumerator: 2 denominator: 5];  
      8. Fraction *frac2 = [Fraction fractionWithNumerator: 1 denominator: 3];  
      9.   
      10. // print frac 1  
      11. printf( "Fraction 1: " );  
      12. [frac1 print];  
      13. printf( "\n" );  
      14.   
      15. // print frac 2  
      16. printf( "Fraction 2: " );  
      17. [frac2 print];  
      18. printf( "\n" );  
      19.   
      20. // this causes a segmentation fault  
      21. //[frac1 release];  
      22.   
      23. // release the pool and all objects in it  
      24. [pool release];  
      25. return 0;  
      26. }  
    • 결과
      Fraction 1: 2/5
      Fraction 2: 1/3
    • 이 예제에서, 모든 메소드는 클래스 레벨 메소드 이다. 객체가 생성된 후에, autorelease가 호출되었다. main 블럭 안에서 객체에 대한 release는 부르지 않았다.
    • 이 예제가 작동하는 원리는 다음과 같다. 매번 retain이 일어났을 경우에는 반드시 release나 autorelease가 불려져야 한다. 객체의 카운터는 1부터 시작한다. 그리고 autorelease를 부르면 1 – 1 = 0 즉 메모리가 해제되게 된다. 따라서 autorelease pool이 해제되면, 모든 객체의 autorelease 호출된 횟수를 세서 [obj release]를 이용해서 객체당 autorelease가 불려진 횟수와 같은 숫자만큼 카운트를 줄여나간다.
    • 위의 주석에 있는 것처럼, 주석 처리된 줄을 주석 해제 시키면 세그먼트 오류가 날 것이다. autorelease가 이미 객체에서 불려졌기 때문에, release를 호출하고, autorelease pool에서 다시 release를 호출하면 이미 nil이 된 객체에서 다시 dealloc을 호출하는 것이 될 테니 올바르지 않다. 수식으로 다시 정리해보면 1(생성) – 1(release) – 1(autorelease) = -1이 되는 것이다.
    • Auto release pools은 동적으로 많은 양의 임시 객체들을 만들어 낼 수 있다. 이 때의 올바른 절차는 먼저 풀을 만들고, 많은 임시 객체를 만드는 코드를 실행을 시킨 다음에 풀을 제거하는 것이다. 혹시 궁금할 경우에 대비해서 이야기 하면, 한번에 1개 이상의 auto release pool을 갖는 것도 가능하다.

Foundation framework 클래스

  • Foundation framework은 C++의 Standard Template Library와 유사하다. 오브젝티브-C에는 진짜 동적 형이 있어서, C++의 탬플릿처럼 조잡하게 코딩하지 않아도 된다. 이 프레임워크에는 자료 구조, 네트워킹, 쓰레드 외 여러가지 것들이 포함되어 있다.
  • NSArray

    • 예제의 출처: “Programming in 오브젝티브-C,” Copyright © 2004 출판사 Sams Publishing. 허가 받고 사용함
    • main.m
      1. #import <Foundation/NSArray.h>  
      2. #import <Foundation/NSString.h>  
      3. #import <Foundation/NSAutoreleasePool.h>  
      4. #import <Foundation/NSEnumerator.h>  
      5. #import <stdio.h>  
      6.   
      7. void print( NSArray *array ) {  
      8. NSEnumerator *enumerator = [array objectEnumerator];  
      9. id obj;  
      10.   
      11. while ( obj = [enumerator nextObject] ) {  
      12. printf( "%s\n", [[obj description] cString] );  
      13. }  
      14. }  
      15.   
      16. int main( int argc, const char *argv[] ) {  
      17. NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];  
      18. NSArray *arr = [[NSArray alloc] initWithObjects:  
      19. @"Me", @"Myself", @"I", nil];  
      20. NSMutableArray *mutable = [[NSMutableArray alloc] init];  
      21.   
      22. // enumerate over items  
      23. printf( "----static array\n" );  
      24. print( arr );  
      25.   
      26. // add stuff  
      27. [mutable addObject: @"One"];  
      28. [mutable addObject: @"Two"];  
      29. [mutable addObjectsFromArray: arr];  
      30. [mutable addObject: @"Three"];  
      31.   
      32. // print em  
      33. printf( "----mutable array\n" );  
      34. print( mutable );  
      35.   
      36. // sort then print  
      37. printf( "----sorted mutable array\n" );  
      38. [mutable sortUsingSelector: @selector( caseInsensitiveCompare: )];  
      39. print( mutable );  
      40.   
      41. // free memory  
      42. [arr release];  
      43. [mutable release];  
      44. [pool release];  
      45.   
      46. return 0;  
      47. }  
    • 결과
      ----static array
      Me
      Myself
      I
      ----mutable array
      One
      Two
      Me
      Myself
      I
      Three
      ----sorted mutable array
      I
      Me
      Myself
      One
      Three
      Two
    • NSArray와 NSMutableArray의 두 가지 종류의 배열이 있다. (파운데이션 클래스에서 가장 데이터에 중점을 둔). 이름에서도 알 수 있듯이 Mutable은 교환 가능하고 NSArray는 그렇지 않다. 다시 말해 NSArray를 만들 수는 있지만, 한번 만든 후에는 길이를 변화시킬 수 없다는 뜻이다.
    • 배열은 생성자에 Obj, Obj, Obj, …, nil 이런 형태로 배열을 초기화 시킬 수도 있다. 여기에서 nil은 끝을 표시해준다.
    • 정렬 부분은 셀렉터(selector)를 사용해서 객체를 정렬하는 법을 보여준다. 셀러터는 배열을 NSString의 대소문자를 구분하지 않는 비교를 사용하라고 지시해 주고 있다. 만약 객체가 여러가지 정렬 방법을 있다면, 사용자가 셀렉터를 이용해서 자신이 원하는 정렬방법을 지정해 줘야 한다.
    • print 메소드에서, 메소드 표시를 사용했다. 이것은 자바의 toString이랑 유사한다. 객체를 NSString으로 표시한 것을 반환한다.
    • NSEnumerator은 자바의 열거형 시스템이랑 비슷하다. while ( obj = [array objectEnumerator] )이 작동하는 원리는 obj가 가장 마지막 객체에 들어가면 nil이 반환되기 때문이다. 보통 C에서는 nil은 0이고, 곧 false이다. 보다 정확하게 하려면 ( ( obj = [array objectEnumerator] ) != nil ) 이 나을지도 모르겠다.

    NSDictionary

    • 예제의 출처: “Programming in 오브젝티브-C,” Copyright © 2004 출판사 Sams Publishing. 허가 받고 사용함
    • main.m
      1. #import <Foundation/NSString.h>  
      2. #import <Foundation/NSAutoreleasePool.h>  
      3. #import <Foundation/NSDictionary.h>  
      4. #import <Foundation/NSEnumerator.h>  
      5. #import <Foundation/Foundation.h<  
      6. #import <stdio.h>  
      7.   
      8. void print( NSDictionary *map ) {  
      9. NSEnumerator *enumerator = [map keyEnumerator];  
      10. id key;  
      11.   
      12. while ( key = [enumerator nextObject] ) {  
      13. printf( "%s => %s\n",  
      14. [[key description] cString],  
      15. [[[map objectForKey: key] description] cString] );  
      16. }  
      17. }  
      18.   
      19. int main( int argc, const char *argv[] ) {  
      20. NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];  
      21. NSDictionary *dictionary = [[NSDictionary alloc] initWithObjectsAndKeys:  
      22. @"one", [NSNumber numberWithInt: 1],  
      23. @"two", [NSNumber numberWithInt: 2],  
      24. @"three", [NSNumber numberWithInt: 3],  
      25. nil];  
      26. NSMutableDictionary *mutable = [[NSMutableDictionary alloc] init];  
      27.   
      28. // print dictionary  
      29. printf( "----static dictionary\n" );  
      30. print( dictionary );  
      31.   
      32. // add objects  
      33. [mutable setObject: @"Tom" forKey: @"tom@jones.com"];  
      34. [mutable setObject: @"Bob" forKey: @"bob@dole.com" ];  
      35.   
      36. // print mutable dictionary  
      37. printf( "----mutable dictionary\n" );  
      38. print( mutable );  
      39.   
      40. // free memory  
      41. [dictionary release];  
      42. [mutable release];  
      43. [pool release];  
      44.   
      45. return 0;  
      46. }  
    • 결과
      ----static dictionary
      1 => one
      2 => two
      3 => three
      ----mutable dictionary
      bob@dole.com => Bob
      tom@jones.com => Tom

장단점

    장점

    • 카테고리
    • 포즈
    • 동적형
    • 포인터 카운팅
    • 유연한 메시지 전달
    • C로부터 적당한 정도로 확장을 해서 복잡하지 않음
    • 오브젝티브-C++을 통해서 C++을 사용할 수 있음

    단점

    • 네임스페이스가 없음
    • 연산자 오버로딩이 없음(이 점은 장점이라고 할 수 도 있지만, 연산자 오버로딩을  쓰면, 코드의 부자연스러운 점을 줄일 수 있다.)
    • 언어 자체적으로 세련되지 못한 점이 있으나, C++이랑 비슷한 수준

추가 정보


최종 수정: April 13, 2004.

한글 번역: September 11, 2010, by Michael Kang

반응형

+ Recent posts

반응형