이 글은 아래의 출처를 수정하여 작성한 글 임을 밝힌다.
<출처 : http://wwwww.kr/30792>
Chap3-1의 추가적인 설명부분이다.
- property 와 synthesize
- 메서드이지만 마치 변수처럼 사용할 수 있는 요소입니다.
- setter와 getter의 역할을 수행하는 메서드입니다.
- 선언(클래스 선언 부에서 작성 - 메서드 선언하는 영역)
@property (특성나열) 자료형 변수명;
- 구현(클래스 구현부에서 작성 - 아무 곳이나 가능)
@synthesize 변수명;
- 위 처럼 선언과 구현을 하면 getter와 setter메서드가 구현 된 것으로 간주 합니다.
01.
1. 이전 프로젝트의 Test.h 파일의 선언 부 수정
02.
#import <Foundation/Foundation.h>
03.
@interface Test : NSObject {
04.
int
value;
05.
}
06.
- (id)init:(
int
)a;
07.
- (
void
)Disp;
08.
- (
void
)add:(
int
)first:(
int
)second;
09.
- (
void
)addWithFirst:(
int
)first withSecond:(
int
)second;
10.
//- (int)value;
11.
//- (void)setValue:(int)n;
12.
@property
int
value;
13.
@end
01.
2. 이전 프로젝트의 Test.m 파일의 메서드 구현 부분 수정
02.
/*
03.
- (int)value
04.
{
05.
return value;
06.
}
07.
- (void)setValue:(int)n
08.
{
09.
value = n;
10.
}
11.
*/
12.
@synthesize value;
01.
3. ClassTest.m 파일의 main 메서드 수정
02.
#import "Test.h"
03.
int
main (
int
argc,
const
char
* argv[])
04.
{
05.
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
06.
Test *obj;
07.
obj = [Test
new
];
08.
[obj setValue:10];
09.
NSLog(@
"value의getter:%d"
, [obj value]);
10.
[pool drain];
11.
return
0;
12.
}
1. property :
- getter 와 setter의 선언을 대신할 수 있는 지시어
- 형식 :
@property (특성 나열) 변수 선언;
2. synthesize
- getter 와 setter 의 구현을 대체
- 형식 :
@synthesize 변수명;
3. 프로퍼티 특성
@property(setter|getter = 메서드명) 자료형 변수명;
메서드를 직접 작성한 경우 연결할 때 사용
@property(readonly|readwrite) 자료형 변수명;
읽기 전용과 읽기와 쓰기 가능 프로퍼티 지정 - 기본은 readwrite
@property(assign|retain|copy) 자료형 변수명;
멤버변수가 객체인 경우 대입방법에 대한 지정 - 객체인 경우 필수
@property(nonatomic) 자료형 변수형;
멀티 스레드 환경에서 상호 배제 코드를 삽입할 것인지 여부
@synthesize 별명 = 원래이름;
변수를 별명으로 synthesize
01.
1. 이전 프로젝트의 Test.h 파일의 선언 부 수정
02.
#import <Foundation/Foundation.h>
03.
@interface Test : NSObject
04.
{
05.
int
value;
06.
}
07.
- (id)init:(
int
)a;
08.
- (
void
)Disp;
09.
- (
void
)add:(
int
)first:(
int
)second;
10.
- (
void
)addWithFirst:(
int
)first withSecond:(
int
)second;
11.
//@property int value;
12.
@property (nonatomic, readonly)
int
value;
13.
@end
1) atomic | nonatomic
atomic : 상호배제코드 포함
nonatomic : 상호배제코드 미포함, 속도가 향상됨, 아이폰SDK 에서는 대부분 이것만 사용
2) readonly | realwrite
readonly : getter만 있음. 값을 넣을 수 없음.
readwrite : getter 와 setter 둘 다 존재.
3) setter | getter = 메서드명
getter : 데이터 타입이 BOOL인 경우 is 삽입을 위하여 사용
4) assign | retain | copy
객체(참조형)인 경우 필수
5) @synthesize 별명 = 원래이름;
int *p = (int *) malloc (4);
*p=10;
int *q = p; // assign : 단순하게 대입
int *q = (int *) malloc(4); //copy - 단점 : 메모리 공간 사용이 많다.
*q = *p;
=================================================================================================
.(dot)을 이용한 접근 : 프로퍼티로 지정된 getter와 setter는 [ ]를 생략하고 .을 이용해서 접근할 수 있다.
=================================================================================================
getter와 setter의 이름을 getter이름 하나로 사용 : = 의 왼쪽이면 자동적으로 setter
여러번 연속해서 사용이 가능하다.
setter의 접근은 객체명.변수명=값; 형태가 된다.
변수는 화살표, 프로퍼티만 .쩜!!
01.
1. 이전 프로젝트의 Test.h 파일의 선언 부 수정
02.
#import <Foundation/Foundation.h>
03.
@interface Test : NSObject
04.
{
05.
int
value;
06.
}
07.
- (id)init:(
int
)a;
08.
- (
void
)Disp;
09.
- (
void
)add:(
int
)first:(
int
)second;
10.
- (
void
)addWithFirst:(
int
)first withSecond:(
int
)second;
11.
@property (nonatomic)
int
value;
12.
@end
01.
2. ClassTest.m 파일의 main 메서드 수정
02.
#import "Test.h"
03.
int
main (
int
argc,
const
char
* argv[])
04.
{
05.
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
06.
Test *obj;
07.
obj = [Test
new
];
08.
obj.value = 10;
09.
NSLog(@
"value의getter:%d"
, obj.value);
10.
[pool drain];
11.
return
0;
12.
}
=================================================================================================
const
=================================================================================================
- 변수를 상수화 시켜주는 예약어
- 일반 포인터 변수 앞에 사용되면 가리키는 자체는 변경할 수 있지만 내용은 변경 불가능
- 일반 변수에 사용되는 경우에는 readonly로 동작
- 일반적으로 클래스의 구현부에서 사용
- 멤버변수에 const가 사용되는 경우 무조건 0으로 사용해야 함
01.
#import <Foundation/Foundation.h>
02.
int
main()
03.
{
04.
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc]init];
05.
const
int
a = 10;
06.
NSLog(@
"a:%d"
,a);
07.
a = 11;
08.
NSLog(@
"a:%d"
,a);
09.
[pool drain];
10.
return
0;
11.
}
01.
int
main() {
02.
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc]init];
03.
int
a = 10;
04.
int
b = 11;
05.
const
int
* p;
06.
p = &a;
07.
NSLog(@
"p가 가리키는 값:%d"
,*p);
08.
p=&b;
09.
NSLog(@
"p가 가리키는 값:%d"
,*p);
10.
*p=11;
11.
NSLog(@
"p가 가리키는 값:%d"
,*p);
12.
[pool drain];
13.
return
0;
14.
}
===========================
char ch[]="Hello";
const char *str = "Hello";
ch[1]='k'; // e를 k로 변경 가능.
str[1]='k'; // error. 변경 불가.
===========================
=================================================================================================
extern 변수
=================================================================================================
- 서로 다른 파일 간에 변수를 공유할 수 있는 개념
- 서로 다른 파일 간에도 변수를 공유해서 메세지를 주고 받을 수 있다.
- 선언 한 후 사용하고자 하는 곳에서 재정의해서 사용해아 함.
- 아이폰에서는 잘 사용하지 않는다.
1) 파일과 파일사이의 공유
2) 프로그램 사이의 데이터 공유 => 아이폰에서 필요없음
아이폰의 앱은 AppDelegate객체에서 출발
1.
Test.h
2.
#import <Foundation/Foundation.h>
3.
extern
int
g_value;
4.
@interface Test:NSObject
5.
-(
void
)setGlobal:(
int
)val;
6.
@end
01.
Test.m
02.
#import "Test.h"
03.
@implementation Test
04.
-(
void
)setGlobal:(
int
)val
05.
{
06.
extern
int
g_value;
07.
g_value = val;
08.
}
09.
@end
01.
Main 파일
02.
#import "Test.h"
03.
int
g_value = 10;
04.
int
main()
05.
{
06.
Test *Obj = [[Test alloc]init];
07.
NSLog(@
"%d"
, g_value);
08.
[Obj setGlobal : 1000];
09.
NSLog(@
"%d"
, g_value);
10.
return
0;
11.
}
=================================================================================================
토탈 예제
=================================================================================================
//day3.m
#import <Foundation/Foundation.h>
//다른 파일에 있는 선언문을 사용하고자 하는 경우에는 헤더파일이 import되어야 합니다.
//Test 라는 클래스의 사용을 위해서 import
//SDK가 제공해주는 클래스를 사용할 때는 < > 안에 헤더파일 이름을 기재해야 하고
//자신이 만든 클래스를 사용하고자 할 경우에는 " " 안에 기재해야 합니다.
#import "test.h"
int main (int argc, const char * argv[]) {
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
//alloc과 init으로 생성 - 정적 타이핑(변수 선언할 때 자료형을 기재)
Test * Obj1 = [[Test alloc]init];
NSLog(@"%@", Obj1);
//Obj1 이 print라는 메서드를 호출
[Obj1 print]; // -가 붙어있으므로 [Test print]; 라고 하면 안됨.
//클래스 메서드이므로 Obj1이 호출할 수 없다.
[Test disp]; //+가 붙어있으므로 오른쪽처럼 하면 안된다. //[Obj1 disp];
//정수 매개변수 1개를 갖는 printWithInt를 호출
[Obj1 printWithInt : 10];
//호출 시 의미까지 호출해야 함
int n;
[Obj1 add:10 :20 :n];
[Obj1 addWithFirst:10 withSecond:20 saveWithResult:n];
//value에 프로퍼티가 지정되어 있으므로 [] 대센이 . 을 이용해서 getter와 setter를 호출할 수 있다.
//getter와 setter모두 getter이름만으로 접근하며 =의 오른쪽에 사용되면 자동적으로 setter가 된다.
//셋터(왼쪽) = 겟터(오른쪽)
/*
[Obj1 setValue:50];
NSLog(@"value : %d", [Obj1 value]);
*/
Obj1.value=50;
NSLog(@"value : %d", Obj1.value);
//new 로 생성 - 동적 타이핑(변수 선언할 때 자료형을 기재하지 않음)
/*
id Obj2 = [Test new];
NSLog(@"%@", Obj2);
*/
[pool drain];
return 0;
}
//
// Test.h
// ClassTest
//
// Created by iMac_23 on 10. 11. 5..
// Copyright 2010 __MyCompanyName__. All rights reserved.
//
#import <Foundation/Foundation.h>
@interface Test : NSObject {
int value;
}
@property int value;
//@propery (readonly) int value ; <- 읽기전용으로 변경하는 방법. 여기선 이렇게 하면 오류 남.
/* getter와 setter
- (int)value;
- (void)setValue : (int)temp;
//property : getter 와 setter의 선언을 대체
//형식 : @property (특성 나열) 변수 선언;
*/
- (void)print; // -는 멤버,객체
+ (void)disp; // +는 클래스
- (void)printWithInt:(int)n;
- (void)add:(int)first:(int)second:(int)result;
- (void)addWithFirst:(int)first withSecond:(int)second saveWithResult:(int)result;
@end
//
// Test.m
// ClassTest
//
// Created by iMac_23 on 10. 11. 5..
// Copyright 2010 __MyCompanyName__. All rights reserved.
//
#import "Test.h"
@implementation Test
/*
//변수의 getter는 변수만 리턴하면 됨
- (int)value
{
return value;
}
//변수의 setter는 매개변수를 변수에 대입하면 됨
- (void)setValue:(int)temp
{
value = temp;
}
*/
@synthesize value;
/* synthesize : getter 와 setter의 구현을 대체
형식 : @synthesize 변수명; */
- (void) print
{
NSLog(@"Hello");
}
+ (void) disp
{
NSLog(@"Hi");
}
- (void) printWithInt:(int)n
{
NSLog(@"n:%d",n);
}
- (void)add:(int)first:(int)second:(int)result
{
result = first + second;
NSLog(@"%d", result);
}
- (void)addWithFirst:(int)first withSecond:(int)second saveWithResult:(int)result
{
result = first + second;
NSLog(@"%d", result);
}
@end
=================================================================================================
상속
=================================================================================================
- 상위 클래스의 멤버를 하위 클래스에게 물려주는 것을 상속이라고 합니다.
- 상위 클래스의 모든 멤버를 물려받습니다.
- 상위 클래스를 super class 또는 base class라고 하며 하위 클래스를 sub class 또는 derived class 라고도 합니다.
- 상속 방법
@interface 클래스이름: 상속하는 클래스
- CocoaTouch에서는 NSObject 클래스가 최상위 클래스이며 모든 클래스는 이 클래스로부터 상속을 받아야만 합니다.
- Cocoa에서는 NSProxy라는 클래스도 최상위 클래스로 취급합니다.
다른 클래스가 NSObject 클래스로부터 상속을 받았다면 그 클래스로부터 상속을 받아도 됩니다.
- NSObject클래스에는 여러 가지 멤버가 정의되어 있습니다.
- isa라는 멤버 변수와 메모리 할당과 관련된 alloc, dealloc, release, retain, finalize 같은 멤버 들을 가지고 있으며 init, initialize, new 등과 같은 초기화 메서드 들도 가지고 있습니다.
- 하위 클래스에서는 상위 클래스의 멤버를 다시 정의하지 않아도 있는 것으로 간주하며 자신의 멤버를 정의하고자 한다면 정의하고자 하는 내용을 기재하면 되고 정의할 내용이 없다면 블록만 연 후 닫아도 됩니다.
- 상속 시 상위 클래스와 하위 클래스에 동일한 멤버 변수의 정의는 안됩니다.
- 상위 클래스의 메서드를 하위 클래스에서 다시 정의해서 사용하는 것은 가능한데 이를 메서드 오버라이딩이라고 합니다.
=================================================================================================
self
=================================================================================================
- 클래스 내에서 객체를 가리키는 숨겨진 포인터
- 셀프는 클래스 정의 내에서 객체가 자기 자신을 리턴시켜야 하거나 자신의 멤버를 명시적으로 호출하는경우 사용
- 클래스 내부에서 자신의 멤버 메서드를 호출하는 경우에도 사용
- Objective-c에서는 메서드 이름만으로는 메서드를 호출할 수 없다.
- 지역변수와 멤버변수의 구분을 위해서도 사용하며 아이폰SDK 에서는 delegate지정에도 많이 사용함
- delegate는 수행해야 하는 메서드 들을 위임 받아서 대신 처리하는 객체
- self.property 와 self->멤버변수 및 멤버변수를 혼동하면 안됨.
- self.property 를 이용하게 되면 프로퍼티에 지정한 동작을 수행하게 됨
- self->멤버변수를 사용하게 되면 변수를 호출한 것이므로 프로퍼티와는 상관없는 동작을 사용하게 됨.
=================================================================================================
super
=================================================================================================
- 상위클래스 객체를 가리키는 예약어
- 상위클래스 멤버와 동일한 멤버를 하위클래스에서 선언하거나 다시 정의하면 상위클래스의 멤버는 가려지므로 상위 클래스의 멤보는 슈퍼를 이용해서 호출해야 함
- 상위클래스에 있는 메서드를 하위클래스에서 재정의 하는것을 메소드 오버라이딩(재정의)이라고 함
- 아이폰SDK 에서 오버라이딩을 하는 경우에는 주의해야 함
- 상위클래스에 정의되어 있는 주요한 기능은 항상 상위 클래스의 메서드를 호출해서 그 작업을 하고 난 후 자신의 작업을 수행해야 함
- loadView같은 메서드는 [super loadView]를 호출하지 않으면 뷰가 화면에 보여지지 않으며 dealloc메서드는 상위클래스의 dealloc을 호출하지 않으면 경고를 발생시킴
iphone SDK에서의 overriding
- dealloc을 재정의하는 경우에는 반드시 마지막에 [super dealloc]을 호출
- 메모리 관리나 화면관리하는 메서드를 재정의 할때는 super의 메서드를 호출하는 것이 바람직
=================================================================================================
다형성과 동적 바인딩
=================================================================================================
- 일반적으로 오버라이딩을 하는 이유는 다형성을 구현하기 위해서이다.
- 다형성은 동일한 메세지에 대하여 서로 다르게 반응하는 성질
- 다형성이 구현되기 위해서는 프로그래밍 언어가 동적 바인딩을 지원해야 함
- 동적 바인딩이란 객체가 컴파이리 시에 자신의 타입을 결정하지 않고 실행(메모리 할당)시에 자신의 타입을 결정 하는 것
- 선언이 될 때 사용된 타입은 무시하고 메모리를 할당받을 때 어떤 타입으로 할당받았느냐에 따라 동작하는 것
- Objective-c는 무조건 동적 바인딩이다.
- 일반적으로 상위클래스 타입으로 선언된 변수에는 하위클래스 타입의 객체를 대입할 수 있다.
정적 타이핑과 동적 타이핑
- 변수를 선언할 때 특정 클래스 타입이라는 것을 명시하는 것을 정적 타이핑이라고 함
- 동적 타이핑 : 변수를 선언할 때는 id타입으로 선언한 후 메모리 할당을 받을 때………….
=================================================================================================
클래스 객체
=================================================================================================
- 클래스도 선언과 구현이 되면 하나의 객체처럼 취급할 수 있다.
//InheritanceTest.m
#import <Foundation/Foundation.h>
#import "Test.h" //헤더파일 임포트
int main (int argc, const char * argv[])
{
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
//Test 클래스 타입의 객체를 생성 - alloc 와 init
Test * Obj = [[Test Alloc]init];
//객체에게 description(NSObject로부터 상속됨)메서드를 실행하게 한 후 내용을 출력
//일반 객체에게 (description이 재정의 되지 않은 클래스로부터 생성)
//description을 호출하면 클래스 이름과 id를 문자열로 리턴
[Obj disp];
NSLog(@"%@",[Obj description]);
//다른 언어이면 경고가 발생하거나 에러가 발생한다
//objective-c에서는 변수를 선언할 때 사용한 자료형은 바인딩하기 위한 자료형이 아니고
//단순하게 객체라는 것을 알려주기 위한 것이므로 타입이 있기만 하면 에러가 아니고
//변수를 생성한 이후에는 무시됩니다.
Obj = [[NSObject alloc]init];
NSLog(@"%d@",[Obj description]);
[pool drain];
return 0;
}
//
// Test.h
// InheritanceTest
//
// Created by iMac_23 on 10. 11. 8..
// Copyright 2010 __MyCompanyName__. All rights reserved.
//
#import <Foundation/Foundation.h>
@interface Test : NSObject {
int val;
//클래스 타입을 갖는 멤버 변수 선언
NSNumber * num;
}
//int val에 대한 프로퍼티 지정(특성은 기본만 사용)
@property int val;
//nonatomic과 retain특성을 갖는 NSNumber * num프로퍼티 생성
@property(nonatomic,retain) NSNumber * num;
//출력하는 메서드 선언
- (void) disp;
@end
//
// Test.m
// InheritanceTest
//
// Created by iMac_23 on 10. 11. 8..
// Copyright 2010 __MyCompanyName__. All rights reserved.
//
#import "Test.h"
@implementation Test
//int val에 대한 synthesize 지정
@synthesize val; //(.h파일에서 프로퍼티 선언하면 .m에서 신서사이즈 선언해야함)
@synthesize num;
- (void) disp;
{
//경고 발생 - 멤버변수와 동일한 지역 변수를 생성해서 멤버 변수가 가려짐
//int val=10;
NSLog(@"Local val:%d",val);
NSLog(@"Member val:%d",self->val);
//num은 아직 할당받지 않아서 retainCount:0
NSLog(@"num의 retainCount:%d",[num retainCount]);
num=[[NSNumber alloc]initWithInt:1000];
//num은 할당받아서 retainCount:1
NSLog(@"num의 retainCount:%d",[num retainCount]);
self.num=[[NSNumber alloc]initWithInt:500];
//num은 할당받은 후 프로퍼티에 정의된 retain으로 대입되므로 retainCount:2
NSLog(@"num의 retainCount:%d",[num retainCount]);
}
/*
- (NSString *)description
{
NSLog(@"메서드 오버라이딩");
retain [NSString stringWitheFormat:@"num:%@",num];
}
*/
//dealloc을 재정의 할 경우에는
- (void) dealloc
{
[num release];
[super dealloc];
}
@end
=================================================================================================
nil포인터
=================================================================================================
- 다른 언어의 null과 유사하며 0의 값을 갖는 포인터 입니다.
- 이 포인터는 어떠한 메시지 처리도 할 수 없습니다.
- nil 포인터가 메시지 호출을 하는 경우 에러는 아닙니다.
- nil 포인터는 메시지 호출을 하려고 하다가 실패하면 예외가 발생해서 프로그램이 종료될 것입니다.
- Iphone SDK 사용 시 주의해야 합니다.
- 메서드가 구현되어 있지 않거나 메서드를 호출하는 리시버가 nil이라면 에러가 아니고 실행 시 런타임에러가 발생합니다.
- 일반적으로 init 메서드가 정상적으로 수행이 되지 않은 경우에도 nil을 리턴합니다.
- 하나의 변수를 사용함에 있어서 메모리 할당을 해제하고 재 사용시 되도록 nil을 대입한 후 재사용하는 것이 바람직합니다.
=================================================================================================
지역 메서드
=================================================================================================
- 선언부에는 없고 구현부에만 존재해서 구현 부분에서만 일시적으로 사용하는 메서드
- 이 메서드를 외부에서 호출할 수 있으며 호출하면 경고가 발생할 것입니다.
- Iphone 프로그래밍에서는 이 메서드는 외부 객체의 이벤트(IBAction)가 될 수 없습니다.
- 상속받은 경우와 혼동하면 안됩니다.
//SequenceTest.m
#import <Foundation/Foundation.h>
#import "Test.h"
int main (int argc, const char * argv[]) {
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
Test *obj1, *obj2;
obj1 = [[Test alloc]init];
[obj1 Disp];
//nil포인터
NSLog(@"%d",obj1);
[obj1 dealloc];
//obj1=nil;
obj2 = [[Test alloc]init];
[obj1 Disp];
[obj2 Disp];
[pool drain];
return 0;
[pool drain];
return 0;
}
//
// Test.h
// SequenceTest
//
// Created by iMac_23 on 10. 11. 8..
// Copyright 2010 __MyCompanyName__. All rights reserved.
//
#import <Foundation/Foundation.h>
@interface Test : NSObject
{
//객체의 일련번호를 지정하기 위해 만든 변수
int number;
}
//number 를 일련번호로 저장하기 위한 초기화 메서드
- (id)init;
//number의 static변수를 출력하기 위한 메서드
- (void)Disp;
@end
//
// Test.m
// SequenceTest
//
// Created by iMac_23 on 10. 11. 8..
// Copyright 2010 __MyCompanyName__. All rights reserved.
//
#import "Test.h"
//static변수 생성 - 한번만 생성
static int sequence = 0;
@implementation Test
//객체 초기화하는 메서드
- (id) init
{
self = [super init];
if(self)
number = ++sequence;
return self;
}
- (void) Disp
{
NSLog("@sequence : %d number : %d\n",sequence,number);
}