본문 바로가기
  • 그냥 하자
iOS

Chap3-2. property,synthesize,atomic,setter,getter,assign,readonly,.(dot),const,extern,상속,self,super,다형성,동적바인딩,nil포인터,지역메서드

by Mash 2012. 3. 21.
반응형


이 글은 아래의 출처를 수정하여 작성한 글 임을 밝힌다. 
<출처 : 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);
}

@end

반응형