2.1 기본 Data Type
일반적으로 어떤 언어든 기본적인 데이터 형은 비슷하다. 왜냐하면 같은 컴에서 돌아가니까...
델파이 4의 새로운 기능으로 세가지 Type이 나온다.
델파이4에서는 일반적인 Interger형(32bit Longint)으로 처리할 수 없는 너무 큰 정수값을 사용하고자 할 때 새롭게 Int64형을 사용할 수 있다.
그리고 StrToInt64와 StrToInt64, StrToInt64Def는 Int64를 지원하는 새롭게 추가된 함수이다. 그러나 몇몇 루틴들(Ord 등)은 Int64형 값을 지원하지 않는다.
또 델파이 4에서는 32비트 부호 없는 정수형(32bit Unsigned Integer Type)인 Unsigned Integer형으로 Longword형이 추가되었다. 기존에 지원되었던 Cardinal형이 이제 델파이 4에서 Longword와 동등한 범위를 지원한다.
마지막으로, 이전 버전에서 48비트 부동 소수점 수로 표현되었던 Real형은 이제 64비트 Double형으로 식별되도록 변경되었다. Double형이 인텔 계열 CPU와의 호환성을 제공하기 때문에, 이와 같은 변경이 성능을 향상시킨다. Real형의 속성들은 이제 Published로 사용할 수 있다.
▶ 정수형 (Integer형)
정수형은 일반적인 숫자를 표현하는데 사용되는 자료형이다. 정수형은 표현할 수 있는 값의 범위에 따라 다시 표와 같이 구분된다.
자료형 |
범 위 |
크 기 |
Shortint |
-128 ~ 127 |
1바이트 / 부호있는 8비트 |
Smallint |
-32768 ~ 32767 |
2바이트/ 부호있는 16비트 |
Longint |
-2147483648 ~ 2147483647 |
4바이트/ 부호있는 32비트 |
Int64 |
-(263) ~ (263)-1 |
8바이트/ 부호있는 64비트 |
Byte |
0 ~ 255 |
1바이트/ 부호없는 8비트 |
Word |
0 ~ 65535 |
2바이트/ 부호없는 16비트 |
Longword |
0 ~ 4294967295 |
4바이트/ 부호없는 32비트 |
Integer |
-2147483648 ~ 2147483647 |
4바이트/ 부호있는 32비트 |
Cardinal |
0 ~ 4294967295 |
4바이트/ 부호없는 32비트 |
▶ 실수형
실수형은 소수점 이하의 값을 다룰 수 있다는 점에서 정수형과 다르다.
자료형 |
범 위 |
유효 자릿수 |
크 기 |
Real |
5.0 * 10-324 ~ 1.7 * 10308 |
15 ~ 16자리 |
8 바이트 |
Real48 |
2.9 * 10-39 ~ 1.7 * 1038 |
11 ~ 12자리 |
6 바이트 |
Single |
1.5 * 10-45 ~ 3.4 * 1038 |
7 ~ 8자리 |
4 바이트 |
Double |
5.0 * 10-324 ~ 1.7 * 10308 |
15 ~ 16자리 |
8 바이트 |
Extended |
3.6 * 10-4951 ~ 1.1 * 104932 |
19 ~ 20자리 |
10 바이트 |
Comp |
-263+1 ~ 263-1 |
19 ~ 20자리 |
8 바이트 |
Currency |
-922337203685477.5808 ~ -922337203685477.5807 |
19 ~ 20자리 |
8 바이트 |
Comp형은 분류상으로는 실수형으로 두었지만, 실제로는 정수형 값이다. 이제는 Int64형을 쓰는 것이 더 효율적이다.(Int64형이 나왔으니깐…) 또한, Currency형도 정확한 돈 계산을 위하여 부동 소수점 연산을 하지 않고 소수점 이하 네 자리만 보존하는 고정 소수점 수이기 때문에 유효 자릿수 이후를 잘라버림으로써 발생하는 Round off오류가 발생하지 않는다. 연산할 때도 자동으로 10000을 곱하고 나누어 주는 기능을 한다. 미국과 같이 달러와 센트 등으로 표기하는 국가에서 사용할 만하지만 우리 입장에서는 Int64형을 쓰는 것이 더 나을 것 같이 보인다.
▶ 문자열형
변수를 String형으로 정의하면 Generic형이 되어 기본적으로 AnsiString형으로 정의된다.
자료형 |
최대 길이 |
필요한 메모리양 |
용 도 |
ShortString |
255문자 |
2 ~ 256바이트 |
과거 버전과의 호환용 |
AnsiString |
231문자 |
4 ~ 2기가바이트 |
8비트 ANSI 문자열 처리 |
WideString |
230문자 |
4 ~ 2기가바이트 |
유니코드 문자열 처리 |
실제로 델파이에서는 주로 Boolean형이 많이 사용되고, 나머지 대수형은 주로 외부 언어나 모듈과 함께 사용된다.
▶ 열거형(Enum형)
열거형은 말 그대로 몇 개의 항목들을 나열하고 그 순서를 값으로 가질 수 있는 자료형이다.
Type Colors = ( Red, Blue, Yellow, Black, White) //Colors형의 변수는 열거한 5가지 값들 중에서 한가지를 가질 수 있다.Var MyColor : Colors;Begin MyColor := Red;End; |
▶ 부분 범위형 (Subrange형)
부분 범위형은 파스칼의 독특한 자료형이다. 부분 범위형은 다른 Ordinal형의 가능한 값 범위의 부분 집합을 의미한다. 예를 들어, 정수들 중에서 1부터 10까지의 정수만을 사용할 수 있는 범위형을 정의한다면 다음과 같이 할 수 있다.
Type MyNumber = 1..10; |
▶ Ordinal형
Ordinal형이라는 것은 순서가 정해진 형을 말한다.
오브젝트 파스칼에서는 Ordinal형으로는 Interger, Character, Boolean, Enumerated, Subrange형이 있다.
실수의 경우 순서가 있다고 할 수는 있지만, 한 값에 대해 바로 다음 순서가 되는 값을 정할 수가 없다. 그러나 정수형의 경우 항상 1씩 증가하므로 다음 값은 현재 값에 대해 +1을 하면 정할 수가 있다. 마찬가지로 앞의 값도 구할 수 있다.
Ordinal형의 기본연산
함수 이름 |
의 미 |
Ord(X) |
X의 순서값(정수)를 돌려주는 함수 |
Pred(X) |
X보다 한 순서 앞의 값을 돌려주는 함수 |
Succ(X) |
X보다 한 순서 뒤의 값을 돌려주는 함수 |
High(변수 또는 형) |
주어진 형에 대해 주어질 수 있는 가장 큰 값을 돌려주는 함수 |
Low (변수 또는 형) |
주어진 형에 대해 주어질 수 있는 가장 작은 값을 돌려주는 함수 |
Inc(X) |
X 값을 한 순서 뒤의 값으로 증가시켜 주는 프로시저 |
Dec(X) |
X 값을 한 순서 앞의 값으로 감소시켜 주는 프로시저 |
표준 함수 중에서 정수형을 받아 들이도록 되어 있는 것들은 대부분 Int64형 값을 32비트로 잘라서 받아 들이게 되어 있다. 하지만, 앞에서도 얘기한 바와 같이 High, Low, Succ, Pred, Inc, Dec, IntToStr, IntToHex 등은 Int64형의 매개변수를 완전히 지원하지만 Ord함수는 받아들이지 못한다.
▶ 집합형 (Set)
집합형은 파스칼에 있는 독특한 자료형이다. 집합형은 기본이 되는 Ordinal타입의 256개 이하의 요소로 구성된 모음을 가질 수 있다.
Type TintSet = set of 1..250;Var Set1, Set2 : TintSet;…Set1 := [1, 3, 5, 7, 9];Set2 := [2, 4, 6, 8, 10]; |
▶ 배열형
배열은 같은 형의 원소로 구성된 순서가 있는 집합이다. 배열은 정적/동적으로 할당될 수 있다.
[정적배열]
정적배열은 보통 부분 범위형을 써서 다음의 형태로 정의한다.
Var MyArray : array[1..100] of integer; |
이렇게 하면 정수의 배열이 1부터 100까지 100개가 MyArray라는 이름으로 만들어진다. 이 상태에서 MyArray[3]은 MyArray배열의 세번째 원소를 가리키게 된다. 기본형 자리에 다시 배열을 만들면 2차원 배열이 된다.
Var MyArray : array[1..10] of array[1..50] of Real; MyArray1 : array[1..10,1..50] of Real;//MyArray와 MyArray1은 같은 뜻이다. |
[동적배열]
동적배열은 델파이 4에서 새로 추가된 기능이다. 동적배열은 크기나 길이를 고정시키지 않는다. 대신에 배열에 값을 할당하거나 SetLength 프로시저를 통해 크기를 변경시킬 때에 동적으로 메모리를 재할당하게 된다.
Var MyDynamicArray : array of Real;…SetLength(MyDynamicArray, 20); |
위와 같이 하면 MyDynamicArray에는 20개의 Real변수가 첨자 0부터 19까지 할당되게 된다. 동적 배열은 항상 0부터 시작하는 정수의 첨자를 갖는다. 2차원 이상의 동적배열을 만들고자 할때는 다음과 같이 array of …를 반복해서 사용한다.
Type TwoDimDynamicArray: array of array of Real;Var TwoDimReal : TwoDimDynamicArray;…SetLength(TwoDimReal, 20); //전체 행을 10개로 지정SetLength(TwoDimReal[0], 5); //첫번째 행에 5개의 실수 배열 |
▶ 레코드형
C/C++ 등에서 struct형과 매우 유사한 구조로 여러 종류의 자료형으로 된 복합 자료형을 제공한다. 레코드형의 각각의 구성 요소가 되는 변수를 필드라고 한다.
Type 레코드형이름 = record // 예약어 record로써 레코드선언을 시작한다. 필드1 : 형1; // 각각의 필드마다 다른 형을 줄 수 있다. … 필드n : 형n;end; // 레코드 선언의 끝 |
Type Tstudent = record Name : String; No : Integer; Rec : Double;end;이렇게 선언한 레코드의 멤버는 다음과 같은 방법으로 다룰 수 있다.var MyRec : Tstudent;Begin MyRec.Name := '홍길동'; MyRec.No := 20; MyRec.Rec := 2.4;End;이것은 With문을 사용하여 다음과 같이 사용할 수 있다.With MyRec doBegin Name := '홍길동'; No := 20; Rec := 2.4;End; |
▶ 포인터형
포인터는 다른 변수의 메모리 주소값을 갖는 변수이다. 포인터가 다른 변수의 주소값을 가지고 있으면 이를 포인터가 그 변수를 가리키고 있다고 말한다.
Procedure Tform1.Button1Click(Sender: Tobject);Var X, Y : Integer; P : ^Integer; // 정수형 변수를 가리키는 포인터 변수 P의 선언Begin X := 17; Y := 0; P := @X; // P에는 X의 주소가 대입된다. Y := P^; // Y에는 P가 가리키고 있는 값이 대입된다. ShowMessage(IntToStr(Y)); //확인 : 17End; |
포인터 변수의 사용법은 다음과 같다.
[포인터 변수의 선언]
위 예의 4번째 줄처럼 포인터 변수를 선언할 때는 그 포인터 변수가 가리킬 대상 변수의 형 앞에 꺽쇠 표시(^)를 붙여서 포인터임을 표시한다.
[포인터 변수에 주소값의 대입]
포인터 변수를 사용하려면 먼저 어떤 주소값을 가지도록 해야 한다. 가리키고자 하는 변수 이름 앞에 @ 연산자를 쓰면 그 변수의 주소값이 얻어진다. 8번째 줄을 참고하라.
[포인터 변수를 통한 값의 참조]
포인터 변수 자체는 주소값이므로 그를 통해 간접적으로 대상을 가리켜야 한다. 이를 위해 형 선언시와는 반대로 꺽쇠 표시(^)를 포인터 변수 뒤에 붙인다 9번째 줄을 참고하라.
2.2 Punctuators
Delphi는 다음의 약속된 기호를 사용한다.
Brackets ('[]')
하나 또는 하나 이상의 brackets를 사용하여 Array 요소를 지정 하기 위해 사용한다.
Parentheses ('()')
조건부, Group expression, Operator 또는 함수 호출이나 함수 매개변수 지정에 사용한다.
Braces ('}')
주석을 사용할 경우 '{' 부터 '}' 까지를 주석으로 본다.
Comma (',')
함수의 매개변수 요소를 구분하기 위한 구분자로 사용한다.
Semicolon (';')
모든 문장의 끝에 사용한다.
Colon (':')
Go to문과 함께 사용되는 분기 지점 표시를 위해 사용한다.
Slashes ('//')
해당 라인을 주석으로 본다.
Equal sign ('=') : 초기화
변수에 초기치를 할당하기 위해 사용한다.
2.3 연산자 / 제어문
연 산 자
▶ 산술연산자
연산자 |
연산 |
연산항 타입 |
결과형 |
+ |
덧셈 |
정수와 실수형에 적용 |
정수나 실수 |
- |
뺄셈 |
정수와 실수형에 적용 |
정수나 실수 |
* |
곱셈 |
정수와 실수형에 적용 |
정수나 실수 |
/ |
실수 나눗셈 |
정수와 실수형에 적용 |
실수 |
div |
정수 나눗셈 |
정수형에만 적용 |
정수 |
mod |
나머지 |
정수형에만 적용 |
정수 |
▶ 논리연산자
연산자 |
연산 |
연산항 타입 |
결과형 |
Not |
Bitwise negation |
정수형 |
정수형 |
And |
Bitwise and |
정수형 |
정수형 |
Or |
Bitwise or |
정수형 |
정수형 |
Xor |
Bitwise xor |
정수형 |
정수형 |
Shl |
Bitwise shift left |
정수형 |
정수형 |
Shr |
Bitwise shift right |
정수형 |
정수형 |
▶ 관계연산자
연산자 |
연산 |
결과형 |
= |
같다 |
Boolean |
<> |
같지 않다 |
Boolean |
< |
작다 |
Boolean |
> |
크다 |
Boolean |
<= |
작거나 같다 |
Boolean |
>= |
크거나 같다 |
Boolean |
▶ 문자열연산자
연산자 |
연산 |
적용 대상 |
결과형 |
+ |
문자열 결합 |
문자열형에 적용 |
String |
제 어 문
▶ 제어문의 종류 |
[판단문] [반복문] [제어문 제어요소] |
▶ IF문
if문에는 2가지 형식이 있다. if .. then과 if .. then .. else.
조건에 만족하는 경우 해당 문장을 수행하고, 조건에 만족하지 않는 경우는 해당 문장을 수행하지 않고 pass한다. 하나의 조건 이외의 다른 조건에 대한 부분 조건의 수행을 달리 하기를 원하는 경우 else if문을 사용한다.
If … then의 문법은 다음과 같다.
if <condition1> thenbegin statement1-1; statement1-2;endelse if <condition2> thenbegin statement2-1; statement2-2;end; |
Ex1. |
if i < 10 thenbegin showmessage('i는 10보다 작다.');endelse if i > 10 thenbegin showmessage('i는 10보다 크다.');end; |
Ex2. |
if i <= 10 thenbegin if i = 10 then showmessage('i는 10이다') else showmessage('i는 10보다 작다.');endelse if i > 10 thenbegin showmessage('i는 10보다 크다.');end; |
If 문은 위의 예처럼 중첩될 수도 있다.
Begin … End 사이에 들어가는 문장의 수가 하나라면 위의 예제처럼 Begin … End 를 생략해도 좋다.
또 한가지 주의할 점은 Else 앞에는 세미콜론(;)을 하면 안된다는 것이다.
▶ Case문
Case문은 복잡한 if 조건을 읽기 좋게 만들 수 있는 대안이다.
Case <variable> of <value1> : <하나 또는 하나 이상의 문장>; <value2> : <하나 또는 하나 이상의 문장>;Else <하나 또는 하나 이상의 문장> //Case값의 어느 경우에도 해당되지 않는 모든 값에 대해 적용된다.End; |
위의 은 Ordinal타입이다(String타입은 유효하지 않다.)
에 나타나는 각 값은 case 문에서 유일해야 한다.
값 중에 과 같은 값을 갖는 것이 없다면 else절에 있는 statement가 실행된다.
Ex. |
Case i of 1..5 : Caption := 'Low'; 6..9 : Caption := 'High'; 0, 10..99 : Caption := 'Out of range';Else Caption := ' ';End; |
▶ For … Do 문
제어변수에 의해 지정된 수만큼 반복작업을 수행한다.
For <제어변수> := <초기값> to <최종값> do statement;또는For <제어변수> := <초기값> downto <최종값> do statement; |
For문장은 <초기값>을 <제어변수>에 할당한다. 그리고 나서 순환 후에 <초기값>의 값을 증가시키거나 감소시키면서 반복적으로 statement를 실행한다. ( for … to 는 증가 / for … downto 는 감소 )
Ex. |
Sum := 0;For X := 1 to 10 doBegin Sum := Sum + X; End;Edit1.Text := IntToStr(Sum); //Sum은 1부터 10까지의 합 |
▶ While문
While문은 컨트롤하는 Boolean식이 참이면 단일의 문장이나 begin … end 블록속에 묶인 일련의 문장들을 반복한다. 만일 Boolean식이 거짓이면 While문의 코드는 한번도 실행되지 않을 수 있다.
While <condition> dobegin Statement1; Statement2;end; |
Ex. |
Sum := 0;X := 1;While X <= 10 Dobegin Sum := Sum + X; Inc(X);end;Edit1.Text := IntToStr(Sum); //Sum은 1부터 10까지의 합 |
이 때, For문은 X를 자동으로 증가시키므로 X를 증가시키는 부분이 필요없었지만, While문은 X를 증가시키는 부분이 필요하다. ▶ (Inc(X))
▶ Repeat문
반복수행을 필요로 하는 문장에 대해 반복수행문을 수행한 후 조건검사를 하기 때문에 반복수행문을 적어도 한번은 수행을 한다.
Repeat statements;Until <condition>; |
Ex. |
Sum := 0;X := 1;Repeat Sum := Sum + X; Inc(X);Until X > 10;Edit1.Text := IntToStr(Sum); //Sum은 1부터 10까지의 합 |
▶ Break와 Continue
두 프로시저 Break와 Continue는 while, repeat, 그리고 for 블록의 실행을 제어한다.
Break문은 프로그램 흐름으로 하여금 반복 구조를 빠져 나오고 Continue문은 루프의 다음 문장을 수행하도록 만든다.
Ex. |
X := 1;// While True는 무한루프이지만 break를 사용하면 빠져나올 수 있다.While True dobegin Inc(X); If X>10 then begin Showmessage('X가 10보다 크다'); Break; end; end;…For X := 1 to 10 do Begin // X가 3으로 나눌 수 있는 수이면 메시지를 뿌려주고 For문의 End절로 넘어간다 if (X mod 3)=0 then begin Showmessage('X는 3의 배수이다'); Continue; end; //Continue문에 걸리면 이문장은 수행하지 않는다. Edit1.Text := Edit1.Text + IntToStr(X); end; |
2.4 프로시저와 함수
오브젝트 파스칼의 프로시저와 함수의 차이점은 단 한가지로 규정지을 수 있다.
프로시저는 결과를 돌려주지 않고, 함수의 결과를 돌려준다는 점이다. 그러나 이 둘 사이에 커다란 구분은 갖지말자. 단지 결과값의 처리를 어떻게 하느냐가 다를 뿐이니깐…
프로시저와 함수를 호출하려면 먼저 필요한 프로시저와 함수를 정의해야 한다.
프로시저와 함수의 정의는 크게 두 부분으로 나누어 진다. 한가지는 프로그램의 다른 부분에서 해당 프로시저와 함수의 선언을 정의하는 부분이고, 다른 한 부분은 실제 프로시저나 함수의 내용을 적는 부분(몇 개의 문장들로 이루어진 블록)이다.
프로시저의 구성은 다음과 같다.
Procedure <프로시저 이름>(매개변수목록);[선언부]begin [문장들]end; |
Procedure는 프로시저의 시작임을 알리는 예약어 이며, <프로시저 이름>은 프로시저를 호출할 때 사용되는 이름이다. (매개변수목록)은 프로시저를 호출한 쪽에서 프로시저에게 넘겨주는 입력값들의 목록이고, [선언부]는프로시저에서 사용할 변수나, 상수, 레이블들을 선언하는 곳이다. 만약 사용되는 변수나 상수들이 없다면 생략가능하다. 마지막 [문장들]은 실제 프로시저의 행위를 정의하는 문장들이다.
다음의 예는 문자열의 순서를 반대로 바꾸고 그것이 폼 상의 한 메모 객체에서 디스플레이되는 프로시저를 보여주고 있다.
Procedure ReverseStr(s: String);Var r: String; i: Byte;Begin // 문자열 변수 r에 널(null)을 설정한다. r := ' '; // 문자열을 마지막 문자부터 첫번째 문자까지 반복한다. for i := length(s) downto 1 do // s내의 문자를 r의 끝에 연결한다. r := r + s[i]; // Memo객체를 비우고 결과를 나타낸다. Form1.Memo1.Lines.Clear; Form1.Memo1.Lines.Add(r);End; |
프로시저 안에 하고싶은 모든 내용(문자를 꺼꾸로 출력하기)을 넣었다.
이제 문자를 꺼꾸로 출력하고 싶으면, ReverseStr이라는 프로시저를 부르기만 하면된다.
함수 선언은 프로시저 선언과 같지만 함수 선언이 함수가 리턴시키는 값의 타입을 포함시켜야 한다는 점이 다르다.
Function <함수 이름>(매개변수목록):<리턴타입>;[선언부]begin [문장들]end; |
다음 함수 Reverse는 앞의 예와 같지만 Reverse가 반대순서로 바뀐 문자열을 메모에 직접 디스플레이 시키는 대신에 리턴시킨다는 점이 다른다.
Function Reverse(s: String) : String;Var r: String; i: Byte;Begin r := ' '; For i := length(s) downto 1 do r := r + s[i]; Reverse := r; // Result := r 도 같은 결과를 얻을 수 있다.End; |
그러면, 함수와 프로시저를 호출하는 문장을 살펴보자.
Procedure Tform1.Button1Click(Sender: Tobject);Begin ReverseStr(Edit1.text); // 프로시저를 호출하는 경우 Memo1.Lines.Add(Reverse (Edit1.Text)); // 함수를 호출하는 경우 End; |
Reverse함수에서는 메모 컴포넌트에 보여주지 않고 결과값만을 받기 때문에, 위와 같이 메모 컴포넌트에 결과값을 넣는 부분이 들어간다.
▶ 매개변수 전달방법
프로시저와 함수는 모두 매개변수를 받을 수 있다. 실제 매개변수의 수와 종류는 일치해야 한다.
각 방법의 매개변수를 유심히 살펴보자.
Call by value
이 방법에서는 변수를 값으로 전달하는 방식으로 컴파일러는 변수의 값을 복사하여 원래 값이 아니라 복사한 값이 전달된다. 그러니까 윈도우 탐색기에서 파일을 복사하여 다른 디렉토리에 붙여쓰기를 하는 것처럼, 변수의 내용을 복사하여 프로시저의 매개변수로 붙여쓰기하는 것과 마찬가지라고 생각하면 좋을 듯 싶다.
그러면 프로시저내에서 이 매개변수를 지지고 볶든 간에, 원래 변수에 저장되어 있던 값들은 그대로이다.
Procedure add(x,y : integer); |
Call by Reference
이 방법은 변수의 값을 복사하여 쓰는 것과는 달리, 방번호는 같은데 변수와 매개변수의 사용하는 이름이 다르다고 생각하자. 100번 방에 있는 값을, 호출할 때는 A(변수)라고 부르고 프로시저에서는 A1(매개변수)이라고 부른다고 가정하면 같은 방에 있는 값이므로 A1이 바뀌면 A도 자연히 따라 바뀌게 되는 것이다.
Procedure ReadData(Var rec : string); |
Call by Const
상수로 매개변수를 전달하는 것은 프로시저 내에서 값을 변경하지 못하도록 컴파일러에 알린다.
아래의 예처럼 매개변수 s를 const로 전달하는 경우는 WriteData라는 프로시저 안에서 s의 값을 바꿀 수가 없다. Read only 변수라고 생각하면 됨.
Procedure WriteData(const s : string); |
2.5 클래스 구조
오브젝트 파스칼에서 가장 큰 특징은 클래스라는 자료 구조를 가지고 있다는 점이다.
클래스의 구조에 대해 알기 위해서 먼저 여러 개념에 대한 이해가 필요하다. 아래의 내용이 좀 이해하기 힘들더라도 일단 천천히 읽어 내려가기 바란다.
▶ 오브젝트, 인스턴스, 클래스
오브젝트 파스칼에서 오브젝트는 레코드형 변수와 마찬가지로 여러 개의 요소들로 이루어진 자료들의 모음이다. 레코드에서 각각의 변수 요소들을 필드라고 하듯이 오브젝트에 대해서도 각각의 변수 요소들을 필드라고 한다. 오브젝트의 필드들은 적절하게 외부에 가려져 있으며, 보통 이들을 직접 참조하는 대신 오브젝트에서 제공하는 프로시저를 호출하여 작업을 처리한다. 이런 프로시저들을 메소드라 하고, 오브젝트는 이와 같이 상태를 보존하는 필드와 동작을 행하는 메소드로 구성된다. 또한 필드에 대한 무책임한 참조로부터 보호하기 위해 적절한 참조 방법을 제공하기도 하는데, 이를 프로퍼티라고 하고, 한 클래스에 속한 필드, 메소드, 프로퍼티 등을 그 클래스의 멤버라고 한다.
클래스는 레코드형과 마찬가지로 일종의 자료형이다. 클래스형으로 정의된 변수는 그 자체로 아직 오브젝트가 되는 것은 아니다. 오브젝트가 되어 메모리에 자리잡기 위해서는 인스턴스화하는 작업이 필요한데, 이를 생성(Create)이라고 한다. 이렇게 생성된 오브젝트를 오브젝트 또는 인스턴스라고 부른다. 오브젝트는 클래스에서 정의한 필드, 프로퍼티, 메소드를 가지고 있게 된다. 오브젝트의 사용이 끝나면 메모리에서 삭제하는 것을 파괴(Destroy)한다고 한다.
클래스를 선언할 때 항상 그 클래스의 모든 멤버들을 선언해야 하는 것은 아니다.
기존에 선언된 클래스를 계승받아 새로운 클래스에 필요한 멤버들만 선택해서 선언하면 된다. 이때, 새로 선언된 클래스를 후손(Descendant)이라 하고, 계승받은 기존의 클래스를 조상(Ancestor)이라고 부른다. 모든 클래스의 선언시에 항상 계승받을 선조 클래스를 지정하게 되어 있으면 생략하면 기본적으로 Tobject 클래스로부터 직접 계승받는 것으로 된다. Tobject 클래스는 모든 클래스의 가장 높은 조상이 되며, 모든 오브젝트가 갖춰야 할 기본적인 기능들을 구현해 놓은 클래스이다. 후손 클래스는 새로운 멤버를 계속 추가할 수만 있고 제거할 수는 없다.
클래스의 선언은 다른 형 선언과는 달리 유닛이나 프로그램의 가장 바깥에서만 행할 수 있다. 보통 유닛의 인터페이스 절에 선언하게 된다.
다음은 클래스 사용법의 예이다.
Type TMyClass = class(TObject) // TMyClass 클래스의 선언----------------(1) …end;…var MyObject : TMyClass; // TMyClass형의 변수 MyObject선언---------(2)…MyObject := TMyClass.Create; // MyObject의 생성------------------------(3)…MyObject.Free; // MyObject의 파괴------------------------(4) |
TMyClass는 TObject로 부터 계승받았다.(1) 그러므로 선조는 TObject가 되고 후손은 TMyClass가 된다. 그리고 (2)에서 TmyClass형으로 변수 MyObject를 선언하였다. 아직까지 오브젝트가 생성된 것은 아니다. 단지 선언만 했을 뿐이다. (3)에서 마침내 생성을 시켜 주었다. 그리고 필요가 없게 되면 (4)에서처럼 파괴를 시켜주어야 한다.
TMyClass형의 Create라는 메소드는 위에서 만들어 주지 않았다. 그러면 어떻게 사용할 수 있었을까?
바로 TObject에 기본적으로 정의되어 있으므로 TMyClass는 TObject에서 상속받기만 하면 TObject의 메소드를 마치 자신의 것인양 쓸 수 있게 되는 것이다.
▶ 클래스멤버의 가시성 지정
앞에서 클래스 안의 필드들이 외부에서 적절하게 가릴 수 있다고 언급한 바 있다. 사실 오브젝트 파스칼은 클래스 선언에 있어서 필드만이 아니라 클래스의 모든 멤버에 대해 외부에서 그것을 참조할 수 있는지의 여부를 상세하게 지정할 수 있는 기능을 가지고 있다.
아래에 설명하는 총 4개의 지시자로 클래스 각각의 멤버의 가시성을 지정할 수 있다.
[Public]
Public지시어는 특별한 제한을 갖고있지 않는 필드나 메소드를 나타낸다. 메소드가 Public으로 선언되면 그 클래스의 어떤 사용자도 사용할 수 있다.
[Private]
Private 지시어는 클래스가 정의된 Unit의 외부에서 접근하거나 알아보지 못하도록 프로시저, 함수나 필드를 정의하기 위해 사용된다. Private로 선언된 식별자의 범위는 선언을 포함하는 모듈로 제한된다. 같은 Unit에서 정의된 개체는 서로의 Private 필드와 메소드를 사용할 수 있다.
[Pretected]
Protected지시어는 Public과 Private중간형태로 파생 클래스이면 그 상위 클래스의 모든 정보를 참조하여 사용할 수 있다.
[Published]
의미는 Public과 같으나 해당 개체의 Object Inspector에 나타나는 속성을 정의하는 곳이다.
Unit UnitA;…type TA = Class(Tobject); Private PriA : Integer; Protected ProA : integer; Public |
출처 : http://blog.heisice.com/1169649571?srchid=BR1http%3A%2F%2Fblog.heisice.com%2F1169649571
'知 > Delphi' 카테고리의 다른 글
한글 안깨지게 자르기 (0) | 2008.08.23 |
---|---|
RS-232, 485의 구분 및 통신코드 (0) | 2008.08.14 |
GRF 파일 저장 문제 (0) | 2008.07.25 |
[바코드] EAN-13 체크 디지트 구하는 루틴 (0) | 2008.07.18 |
KBM_Memory_Table 사용 DBGrid 예제 (0) | 2008.05.08 |