objective c 프로그램
모든 클래스에서 객체는 id라는 특별한 형태로 표현된다.
id obj;
메시지 표현식
어떤 객체 obj에 메세지 msg를 보내려면 아래과 같이 작성한다.
[obj msg]
참고로 메시지 표현식은 리시버 객체(obj)가 그 메시지를 처리한 결과값을 리턴한다.
메시지에 인수가 있으면 메시지 키워드 끝에 : 를 붙여서 인수가 있음을 나타낸다.
[printInfo setLeftMargin: 60.0];
인수가 두개 이상 있을때는 콜론을 붙이고 다른 키워드를 추가한다.
[printInfo setLeftMargin: 60.0 setRight: 90.0];
객체에게 일을 시킬려면?
id형 변수를 선언하는 것만으로는 변수에 객체가 저장되지 않는다. 객체에게 일을 시킬려면 우선 클래스에서 인스턴스를 생성해야 한다.
Objective c는 클래스에 메시지를 보내서 인스턴스를 생성한다.
[클래스명 alloc]
이렇게 만든 인스턴스는 메모리에 필요한 영역이 확보되었다는 것일 뿐이므로, 보통은 이 다음에 바로 초기화 해야한다. 초기화 메서드는 초기자(이니셜라이저)라고 부른다. 초기자 역할을 하는 메서드로 무엇이 있을지는 클래스 마다 다르며, 클래스에 따라서는 여러 초기자를 제공하기도 한다.
Cocoa는 초기자가 init이거나 메서드명이 init으로 시작되어야 한다.
[[클래스 alloc] init];
인스턴스를 생성할 때, 항상 alloc 메시지 표현식 다음에 초기자가 오는 습관을 기르면 좋다. 초기화가 인스턴스 정보를 리셋하지 않는다. 초기자에서 하는 초기화는 인스턴스가 생성된 직후 한 번만 이루어진다. 인스턴스 변숫값을 초깃값으로 돌리는 등의 리셋에 해당하는 처리가 필요하면 초기자가 아닌 다른 메서드를 사용해야 한다.
클래스는 어떻게 정의하나?
objective c 에서는 클래스를 인터페이스 부분과 구현부분을 따로 나누어서 작성한다. 먼저 인터페이스에서는 클래스명 오른쪽에 부모 클래스 명을 적어준다. 아래에는 NSObject를 작성해 주었다. 그후 클래스의 인스턴스 변수와 메서드를 선언한다. 인터페이스는 보통 헤더 파일로 만들고 클래스를 사용하는 모듈에서 참조하도록 한다. @interface와 @end는 컴파일러 지시자라고 부르는 식별자다. 인터페이스의 시작과 끝을 의미한다.
정의부분은 어떻게 만드나?
#import <Foundation/NSObject.h>
@interface Volume : NSObject
{
//인스턴스 변수 선언
int val;
int min, max, step;
}
//반환값이 존재하는 메소드 선언
- (id)initWithMin:(int)a max:(int)b step:(int)s;
- (int)value;
@end
구현부부은 어떻게 만드나?
@implementation은 구현 부분의 시작을 뜻하는 컴파일러 지시자이다. 구현부분에는 슈퍼 클래스명을 적지 않는다. 인터페이스에서 선언한 메서드는 구현 부분에서 반드시 정의해야 한다. 인터페이스에서 메서드를 선언하지 않았다면, 구현 부분에 메서드 정의가 하나도 없을 수 있다. 메서드 내부에서는 해당 클래스 인스턴스 변수에 자유롭게 접근할 수 있다. 아래 예제에서 val, max, step은 인스턴스 변수이다.
#import "Volume.h"
@implementation Volume
- (id)initWithMin:(int)a max:(int)b step:(int)s
{
self = [super init];
if (self != nil) {
val = min = a;
max = b;
step = s;
}
return self;
}
- (int)value
{
return val;
}
@end
클래스 정의 예제
음량을 조절하는 클래스 Volume이 있다. 이 클래스에는 최솟값, 최대값, 변경폭을 초기 설정하는 메서드와 값을 하나 올리는 메서드, 값을 내리는 메서드가 있다.
- (id)initWithMin:(int)a max:(int)b step:(int)s 메소드 안에 있는 [super init] 구문은 슈퍼 클래스 NSObject의 초기화 메시지 호출을 의미한다. nil은 객체이며 무효값이라는 의미의 상수이다. 슈퍼클래스에서 돌아온 값이 무효값이라면 초기화 되지 않는다.
아래예제의 메소드에서는 반환값이 self인 메소드가 있다. self는 메시지를 받아서 해당 메서드를 처리하는 인스턴스 객체이므로 돌아온 값에 다시 메시지를 보낼 수 있다.
클래스 정의부분
#import <Foundation/NSObject.h>
@interface Volume : NSObject
{
int val;
int min, max, step;
}
- (id)initWithMin:(int)a max:(int)b step:(int)s;
- (int)value;
- (id)up;
- (id)down;
@end
클래스 구현부분
@implementation Volume
- (id)initWithMin:(int)a max:(int)b step:(int)s
{
self = [super init];
if (self != nil) {
val = min = a;
max = b;
step = s;
}
return self;
}
- (int)value
{
return val;
}
- (id)up
{
if ((val += step) > max)
val = max;
return self;
}
- (id)down
{
if ((val -= step) < min)
val = min;
return self;
}
@end
실행부분
#import "Volume.h"
#import <stdio.h>
int main(void)
{
id v, w;
v = [[Volume alloc] initWithMin:0 max:10 step:2];
w = [[Volume alloc] initWithMin:0 max:9 step:3];
[v up];
printf("%d %d\n", [v value], [w value]);
[v up];
[w up];
printf("%d %d\n", [v value], [w value]);
[v down];
[w down];
printf("%d %d\n", [v value], [w value]);
return 0;
}
컴파일
Objective C는 컴파일러인 clang을 사용해서 컴파일 한다. Cocoa 환경에서는 시스템이 제공하는 클래스 및 함수를 프레임워크라는 구조를 가진 동적 라이브러리로 제공한다. 특히 Foundation 프레임워크는 Objective c의 기본적인 기능을 지원하므로 Mac OS X 와 iOS 양쪽에 다 들어 있다. 위의 파일을 한곳에 모아서 voltest.m 파일을 만든다.
-framework는 프레임워크를 지정하는 옵션으로, 컴파일(그리고 링크) 할때 Foundation 프레임워크를 사용하기 위해 사용했다.
clang voltest.m -framework Foundation
a.out 파일이 만들어 진다. 실행파일명을 지정하려면 -o 옵션을 사용한다. 또한 컴파일 할때 경고를 자세히 출력하고 싶으면 -Wmost 나 -Wall 옵션을 사용한다.
분할 컴파일
위에서는 인터페이스, 구현부분, main 함수를 모두 파일 하나에 담아서 실행했다. 보통은 각 클래스마다 파일을 따로 만든다. 클래스 하나당 파일 두개를 만든다.
1.인터페이스 파일
2.구현파일
컴파일에서 링크까지 한번에 끝내고 실행파일명을 vol로 지정
clang -o vol main.m Volume.m -framework Foundation
다음은 객체 파일 (확장자 .o)을 작성하고 링크해서 실행파일을 만드는 방법이다.
clang -c main.m
clang -c Volume.m
clang -o vol main.o Volume.o -framework Foundation
'아이폰 개발 > Objective C' 카테고리의 다른 글
objective c 동적결합 (0) | 2020.12.26 |
---|---|
objective c 상속과 클래스 (0) | 2020.12.25 |
objective c 객체 개념 (0) | 2020.12.25 |
2장 클래스 (0) | 2020.08.23 |
1장 객체지향으로의 항해 (0) | 2020.08.23 |