'Objective C/클래스, 객체, 메서드'에 해당되는 글 6건

  1. 2010.03.27 self 키워드와 인수 이름 없는 메서드 2
  2. 2010.03.27 static 키워드
  3. 2010.03.27 메서드내에서 활용하는 변수....지역변수
  4. 2010.03.27 인터페이스와 구현파일 만들기 1
  5. 2010.03.01 setter와 getter만들기
  6. 2010.03.01 클래스 만들기
Actionscript에서 흔히 사용하는 this와 같은 개념으로 self는 자기자신을 가리키는 키워드이다.
만약 어떠한 클래스에 pow라는 메서드가 있고 팔요한 인수를 2개받는다고할 때 접근은 아래와 같다.
[ self pow:2 index:4 ]

* 참고 : 인수 이름 없는 pow메서드
-(void) pow:(int) value1 index:(int) value2
{
int  i, tmp;
tmp = value1;
for( i=1; i<value2; i++ ){
tmp *= tmp;
}

NSLog(@"%i",tmp);
}

두번째 인수의 이름을 설정하지 않으면 아래와 같이 선언할 수 있다.
-(void) pow:(int) value1:(int) value2
{
int  i, tmp;
tmp = value1;
for( i=1; i<value2; i++ ){
tmp *= tmp;
}

NSLog(@"%i",tmp);
}
또한 이런 경우에는 아래와 같이 메서드 접근자를 바꾸어야 한다.
[ self pow:2 :4 ]


Posted by 버터백통
어떠한 변수의 값을 계속 참고하고자 할때는 메모리에 올려두어 접근하도록한다. 그 때 정의하는 것이 static키워드이다.
Fraction클래스에 count라는 함수를 두어 구현파일 내에서 메서드 실행시 이 count라는 메서드를 호출하여 몇번이나 Fraction메서드를 싱핼하는지 체크해 보았다.

-(void) count

{

static int cnt = 0;

++cnt;

NSLog(@"call instance method :%i",cnt);

}


위처럼 변수/객체에 static을 붙여 값을 유지 시킨다. 

Posted by 버터백통
뭐... 사실 다들 알고 있고 많이 사용하지만 변수의 종류를 다시 한 번 정리하면 흔히 멤버변수라면 인스턴스 변수를 말하는데 그것은 클래스변수로서 외부에서도 접근이 가능하며 해당값을 설정하여 그 클래스에서 적절히 연산하고 이를 반환하거나 사용한다. 하지만 단순히 메서드 내부에서만 사용하는 임시적인 변수또한 필요하다. 가령 반복문에서 반복의 범위를 결정할 때 사용하는 변수(흔히 i나 j)등 또는 메서드가 종료하면 필요가 없는 변수들이 그러하다. 이러한 변수를 지역변수라고 하며 이 지역변수는 메서드가 종료하면 이러한 변수의 값은 사라진다.

이번에는 Fraction클래스에 분수를 더하면 최대공약수를 표현하는 메서드 reduce를 구현한다.

-(void) reduce

{

int u = numerator;

int v = denominator;

int tmp;

while (v!=0) {

tmp = u%v;

u = v;

v = tmp;

}

numerator /= u;

denominator /= u;

}


reduce를 구현하는 이유는 종전의 클래스에서 add메서드를 실행할 경우 가령 1/4+1/2 = 6/8로 나오기 때문이다 따라서 이를 3/4로 표현하기 위함이다. 그보다...reduce함수안에 지역변수 u,v,tmp를 선언하여 그 값을 초기화하고 활용하고 있다. 메서드가 종료하면 이 값들은 사라지므로 메모리에 남겨두어 나중에라도 값을 참고하고자 한다면 static키워드를 사용해야 한다.

Posted by 버터백통
프로젝트를 만들어 command+N을 눌러 새로운 파일을 만든다.

이미지 처럼 cocoa프레임워크에서 Objective-C class아이콘을 선택한다.

파일 이름을 적당히 적고 Also create "ClassName.h"를 선택하면 헤더파일(인터페이스)을 같이 생성할 수 있다.
Finish를 누르면 *.h와 *.m파일이 같이 생성된다.

이번에는 간단히 분수식을 표현하는 클래스 Fraction을 만들어 테스트한다.
아래는 Fraction.h의 코드이다.

#import <Foundation/Foundation.h>



@interface Fraction : NSObject {

인스턴스 변수를 설정 

int numerator, denominator;

}

프로퍼티설정

@property int numerator, denominator;


-(void) print;

-(void) setTo:(int) n over:(int) d;

-(double) operation;

-(void) add:(Fraction *) f;


@end


아래는 Fraction.m의 구현파일 내용이다.


#import "Fraction.h"


@implementation Fraction

@synthesize numerator,denominator;


-(void) print

{

NSLog(@"%i/%i",numerator, denominator);

}


-(void) setTo:(int) n over:(int) d

{

numerator = n;

denominator = d;

}


-(double) operation

{

if( denominator != 0 ){

return (double) numerator/denominator;

}else{

return 1.0;

}

}



-(void) add:(Fraction *) f

{

// 분수를 더하기

//a/b + c/d = ((a*d)+(b*c))/(b*d)

property에 dot notation으로 접근

numerator = (numerator * f.denominator) + (denominator * f.numerator);

denominator = denominator * [f denominator];

}



@end

구현파일을 보면 각각의 값을 설정하고 연산하고 두 분수를 더하는 메서드가 선언되어있다.

* 참고 : 위에  import시에 <>와 ""가 있다 <>는 시스템파일을 임포트 하는 것이며 ""는 로컬파일을 임포트한다. 로컬파일을 임포할 경우 같은 경로의 파일을 최우선적으로 검색한다.

Posted by 버터백통
Objc에서 클래스 메서드는 다른 곳에 선언된 인스턴스 변수를 참조하지 못한다.(어쩌면 당연한 일이다...모든 객체와 데이터는 캡슐화가 되어야 하기때문이기도 하지만 자연스레...그렇게들 알고있으니까...다 그래!)  따라서 헤더파일에서 @property를 선언하고 @synthesize하여 해당 변수의 setter와 getter를 자동으로 설정하여 값을 참조하고 설정할 수 있는데 아직 NS객체들에 대하여 깊이 모르므로 지금은 
그냥 setter/getter를 함수로 만들어 사용하여 본다.

#import <Foundation/Foundation.h>


//-------------- interface section -----------------

@interface Fraction : NSObject

{

int numerator;

int denominator;

}


-(void) print;

/*

 클래스메서드는 인스턴스 다른 곳의 인스턴스변수에 접근할 없다

 따라서 함수 setter/getter 만들어 함수의 return값을 통해 인스턴스 변수의 값을 참조할 있다.

 또는 헤더파일에서 @property 설정할 있다. 그러면 자동으로 setter/getter 사용 있도록 속성을 설정할 있다.

 actionscript 다르게 같은 이름의 변수와 함수명에 대하여 에러를 발생하진 않는다.

 */

-(void) setNumerator:(int) n;//numerator setter

-(void) setDenominator:(int) d;//denominator setter


-(int) numerator; //numerator getter

-(int) denominator;//denominator getter

@end


//--------------- implementation section ---------------

@implementation Fraction


-(void) print

{

NSLog(@"%i/%i", numerator, denominator);

}


//인스턴스 변수의 setter부분

-(void) setNumerator:(int) n

{

numerator = n;

}

-(void) setDenominator:(int) d

{

denominator = d;

}


//인스턴스 변수의 getter부분

-(int) numerator

{

return numerator;

}

-(int) denominator

{

return denominator;

}

@end


//--------------- program section ----------------

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

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

    // insert code here...

    Fraction*myFraction = [Fraction new];

    [myFraction setNumerator:1];

    [myFraction setDenominator:3];

    NSLog(@"The Value of myFraction is %i/%i", [myFraction numerator] , [myFraction denominator]);

    [myFraction release];

    [pool drain];

    return 0;

}


위의 코드는 getter함수를 만들어 출력시에 인스턴스가 가지고 있는 변수를 반환하는 함수로 접근하여 값을 받아와 출력하였다.
또한 인스턴스 생성시 alloc와 init의 두가지 행동을 하나로 합하여 new라는 메서드로 처리하였다.
Posted by 버터백통
Objective-C에서 실행할 수 있는 클래스를 만들기 위해서는 논리적으로 크게 3가지 부분으로 나누어진다.
@interface
인터페이스는 보통 *.h로 따로 나누기도하고 *.m파일 안에 포함시키기도한다.
인터페이스의 역할은 상속받은 부모클래스 선언과 테이터 요소(인스턴스 변수), 메서드를 선언한다.
인터페이스의 형태는 아래와 같다.
@interface 클래스이름:부모클래스이름
{
멤버변수선언
}
메서드선언
@end
인터페이스를 반드시 선언하여야 컴파일러에게 사용할 것들은 준비시킨다.

@implementation
인터페이스에서 선언한 메서드의 구현을 담당하고 보통 *.m파일 안에 선언되며 실제 실행할 명령문을 중괄호'{명령문}'안에 작성한다.
구현의 형태는 아래와 같다
@implementation 클래스이름:상속받은 부모클래스 이름(보통은 생략) 
메서드 설정
@end

program
위에서 만든 인스턴스들에 값을 설정하고 실제 사용할 부분이며 어딘가에 선언된 main루틴 안에서 실행한다.
이부분에서 변수에 값을 설정하고 메서드에 메시지를 보낸다.

아래는 분수를 출력하는 클래스이다. 별도의 헤더파일 없이 objc파일 안에 interface를 선언하였다.
 

#import <Foundation/Foundation.h>


//-----------interface section ----------

@interface Fraction : NSObject

{

int numerator;

int denominator;

}


-(void) print;

-(void) setNumerator:(int) n;

-(void) setDenominator:(int) d;


@end


//-----------implementation section ----------

@implementation Fraction


-(void) print

{

NSLog(@"%i/%i",numerator,denominator);

}


-(void) setNumerator:(int) n

{

numerator = n;

}


-(void) setDenominator:(int) d

{

denominator = d;

}


@end


//-----------program section ----------


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

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

//인스턴스 생성 초기화 : * 사용하여 사용할 클래스의 레퍼런스 또는 포인터를 의미

Fraction*myFraction = [[Fraction alloc] init];

/*

또는 아래처럼 순서대로 설정

myFraction = [Fraction alloc]; - Fraction형을 myFraction으로 지정하다(인스턴스를 생성하다,메모리에 할당하다)

* alloc 부모클래스에서 상속받은 것이므로 별도로 구현할 필요가 없다.

* 클래스에 alloc 메시지를 보내 클래스의 새로운 인스턴스를 반환 받는다.

* 반환된 클래스는 myFraction 저장된다.

    * alloc 객체의 모든 인스턴스 변수를 0으로 초기화 한다. 하지만 충분하지 않음으로 init으로 초기화 하여야 한다.

    (alloc 통해 초기화 것은 Fraction객체이며 별도로 myFraction 초기화 하기위해 인스턴스에 init메시지를 보낸다


myFraction = [myFraction init]; - 인스턴스 myFraction init(설정하다 or 생성하다.)

* 클래스 인스턴스(myFraction) 초기화 한다.

*/

//변수값 설정

[ myFraction setNumerator : 1 ];

[ myFraction setDenominator : 3 ];

//myFraction 출력 메서드 호출

NSLog(@"The value of myFraction is :");

myFraction.print;

//myFraction 인스턴스가 사용한 메모리 해제

* referance count에서 1 감소하여 rc 0이되면 시스템은 객체가 필요없다고 인식하고 메모리에서 제거한다.

[myFraction release];


//시스템에 의하여 foundation에서 사용한 모든 객체풀을 사용하고 나면 시스템에서 자동으로 release하도록 한다.

[pool drain];

    return 0;

}


실행하면 콘솔창에 'The value of myFraction is :'와 '1/3'이라고 출력한다.

인스턴스 변수선언
int numerator; 
(데이터타입 변수명)

인스턴스 메서드 선언
반환 값이 없는 경우
-(void) print;
반환값이 없고 인수가 있는 경우 - 함수이름 끝에  :  를 선언하여 인수를 받는 메서드로 선언한다. 
-(void) print:(NSString) msg;
반환값이 있고 인수가 있는 경우
-(int) setNumerator:(int) n;
반환값이 있고 인수가 없는 경우
-(BOOL)  returnMsg;

메서드 구조
- (반환형) 메서드이름:(인수형) 인수이름;
메서드의 앞에  " - "는 메서드 형태이다 (-)인 경우는 컴파일러에게 인스턴스 메서드라고 알려주고 (+)는 클래스 메서드라고 알려준다. 

Posted by 버터백통