본문 바로가기
Delphi/문법

객체지향 언어로서의 오브젝트 파스칼 2편

by MonoSoft 2021. 6. 7.
728x90
반응형

객체지향 언어로서의 오브젝트 파스칼 2편

 

클래스와 객체 (Classes and Objects)

 

■ 델파이 OOP에 대한 문법적인 고찰

 

구체적인 예제에 들어가기 전에, 델파이의 OOP에서 나오게 되는 

중요한 개념들과 문법적인 특징에 대해서 알아보도록 하자.

 

1. 필드 (Fields)

필드는 객체에 속해있는 일종의 변수라고 이해하면 된다. 

필드는 클래스 형을 포함해서 어떤 데이터 형으로도 선언해 사용할 수 있다. 

필드를 선언하려면 단순히 변수를 선언하듯이 하면 된다. 

예를 들어, 다음의 선언부는 TNumber라는 컴포넌트를 선언하는데, 

여기에는 Int라는 정수 필드만을 가지고 있다.

 

type

TNumber = class

  Int: Integer;

end;

 

2. 메소드 (Methods)

메소드는 클래스와 연관되어 있는 프로시저나 함수를 말한다. 

메소드를 호출할 때에는 반드시 객체를 지정해야 하며, 

메소드는 그 객체 위에서 동작한다는 점이 일반적인 프로시저나 함수와의 차이점이다. 

 

예를 들어 다음의 코드를 살펴보자.

SomeObject.Free;

이 코드는 SomeObject라는 객체의 Free 메소드를 호출한다.

 

3. Inherited 키워드

메소드를 구현할 때 inherited라는 키워드를 사용하면 클래스의 

조상이 가지고 있던 메소드를 호출하게 된다. 

보통 메소드를 오버라이드할 때, 그 메소드의 기능을 추가하기 위해 

일단은 조상 클래스의 메소드를 호출하고 나서 부가적인 기능을 수행하거나, 

사전 작업을 지정한 후 마지막에 조상 클래스의 메소드를 inherited 키워드를 이용하여 

호출하는 것이 전형적인 방법이다.

 

4. Self 지시어

메소드의 구현부분에 Self라는 지시어를 사용하면, 

이 지시어는 메소드가 실행되는 객체를 지칭하는 것이다. 

예를 들어, 다음의 코드는 TCollection 클래스의 Add 메소드를 구현한 부분이다.

 

function TCollection.Add: TCollectionItem;

begin

  Result := FItemClass.Create(Self);

end;

 

여기에서 Add 메소드는 FItemClass 필드에 의해 참조되는 Create 메소드를 호출하는데, 

이 필드는 항상 TCollectionItem의 자손이다. 

TCollectionItem.Create 메소드는 TCollection 형의 파라미터를 하나 가지기 때문에, 

Add가 호출될 때 TCollection 인스턴스 객체를 넘겨 준다.

 

5. 프로퍼티 (Properties)

프로퍼티는 필드와 마찬가지로, 객체의 속성을 정의하는 것이다. 

그렇지만 필드가 단지 내용이 변경되거나, 검사할 때 사용되는 

단순한 저장소의 역할을 하는데 비해 프로퍼티는 데이터를 읽고, 

쓰는 특별한 동작과 연관되어 있다. 

프로퍼티는 객체의 속성에 접근할 수 있는 제어권을 제공한다. 

프로퍼티에 대한 보다 자세한 내용은 제 4부의 내용을 참고하기 바란다.

 

■ 클래스의 선언, 생성, 파괴

클래스는 사용자가 정의한 데이터 형이다. 

클래스는 내부적인 데이터와 메소드를 가지고 있으며, 

유사한 많은 객체들의 전반적인 특징과 행동들을 정의한다. 

이에 비해 객체는 클래스의 구체적인 변수로, 실제로 메모리를 차지하게 되는 인스턴스이다.

 

오브젝트 파스칼에서 새로운 클래스 데이터 형을 선언하는 구문은 다음과 같다.

 

type

TPerson = class

  Name, ID: string;

end;

 

위의 코드는 TPerson이라는 클래스를 선언하고, 

이 클래스의 필드인 Name, ID를 정의했다. 

델파이에서는 일반적으로 모든 클래스의 이름 앞에는 T자를 붙이도록 되어 있다. 

이것은 강제 사항이 아니지만 관습을 따르는 것이 아무래도 좋을 것이다. 

위의 선언문을 보면 마치 레코드 선언과 비슷하다는 것을 알 수 있을 것이다. 

클래스의 상속을 하는 구문은 class 키워드 옆에 괄호를 치고 

이 안에 상속 받을 클래스의 이름을 적어넣으면 된다.

 

TPerson = class(TObject)

 

라는 구문은 TObject라는 클래스에서

상속받는 TPerson 클래스를 선언하는 구문이다.

 

이들에 접근하기 위해서는 다음과 같은 방법을 이용하면 된다.

 

var

  Person: TPerson;

begin

  Person.Name := ‘정지훈’;

  Person.ID := ‘ttolttol’

end;

 

그러나, 위의 코드는 실제로 실행되지 않는다. 

이는 TPerson이라는 클래스의 변수인 Person을 선언했지만, 

실제 이 클래스의 인스턴스가 생성되지 않았기 때문이다.

 

cf. 오브젝트 파스칼에서는 클래스 형으로 선언된 각 변수 들이 각각의 

객체의 값을 가지고 있는 것이 아니라, 객체에 대한 참조값(reference), 

즉 그 객체가 저장된 메모리 위치의 포인터를 가지고 있는 것이다. 

이러한 패러다임을 ‘객체참조 모델 (object reference model)’이라고 한다. 

 

그러므로 아래와 같이 변수를 선언하면, 

var Person: TPerson; 메모리에 객체가 만들어지는 것이 아니라 

그저 객체에 대한 메모리의 위치가 정해지고, 

여기에 대한 참조값이 Person 변수에 저장되는 것이다. 

 

그러므로, 실제로 객체의 인스턴스를 사용하려면 인스턴스를 직접 만들어야 한다. 

폼에 추가하는 컴포넌트의 인스턴스는 델파이에 의해 자동으로 만들어진다.

객체의 인스턴스를 만들기 위해서는 그 객체의 생성자(constructor)인 

Create 메소드를 사용하면 된다. 

 

생성자는 새로운 객체를 위해 메모리 배치를 하고 

초기화 시키는 특수한 프로시저이다. 

이러한 생성자는 델파이의 객체 모델의 가장 기본적인 클래스인 

TObject에서 상속받게 되므로, 개발자들은 아무 걱정없이 이를 사용할 수 있다. 

 

아래의 코드를 보자.

var

  Person: TPerson;

begin

  Person := TPerson.Create;

  Person.Name := ‘정지훈’;

  Person.ID := ‘ttolttol’;

end;

 

TPerson.Create 구문에 의해 실제 객체가 생성된다. 

 

이 Create 메소드는 TObject 클래스의 constructor로서,

모든 클래스가 이를 상속하게 된다.

그러므로, TPerson = class 와 TPerson = class(TObject) 는 같은 의미이다.

이렇게 일단 객체를 생성했으면 이를 결국에는 삭제해야 한다. 

 

이때에는 Free 메소드를 호출하면 된다.

Free 메소드 역시 TObject 클래스의 메소드이다. 

이와 같이 필요할 때 객체를 만들어서 사용하고

일이 끝나면 없애 버리는 식으로 사용하면 된다.

그럼, 이를 이용해서 간단한 예제를 만들어 보도록 하겠다.

다음과 같이 에디트 박스 2개와 버튼 4개를 폼 위에 올려 놓고, 

각 버튼의 Name 프로퍼티를 btnCreate, btnFree, btnAssign, btnShow로 설정하자 

 

그리고, Caption 프로퍼티를 ‘생 성’, ‘해 제’, ‘대 입’, ‘보 기’로 설정한다. 

각 에디트 박스의 Text 프로퍼티는 지운다. 유닛의 type 문장에 TPerson 클래스를 선언하고, 

전역변수 Person을 선언한다. 그리고, 각 버튼의 OnClick 이벤트 핸들러를 아래와 같이 작성한다.

 

type

  …(중략)

TPerson = class //클래스 선언부

  Name, ID: string;

end;

 

var

  Form1: TForm1;

  Person: TPerson; //전역변수 선언

 

procedure TForm1.btnCreateClick(Sender: TObject);

begin

  Person := TPerson.Create; //인스턴스 생성

end;

 

procedure TForm1.btnAssignClick(Sender: TObject);

begin

  Person.Name := Edit1.Text; //에디트 박스의 값을 대입

  Person.ID := Edit2.Text;

end;

 

procedure TForm1.btnShowClick(Sender: TObject);

begin

  ShowMessage ('안녕하세요 ? '+Person.Name+ '씨, 당신의 ID는 '+Person.ID+'입니다.');

end;

 

procedure TForm1.btnFreeClick(Sender: TObject);

begin

  Person.Free;

end;

4개의 버튼에 대한 이벤트 핸들러를 이와 같이 작성하면

‘생성’ 버튼을 클릭하면 TPerson 클래스의 인스턴스가 생성되어 

Person 변수에 대입되고, ‘대입’ 버튼을 클릭하면 Person 객체의 Name, ID 필드에 

에디트 박스의 내용이 대입된다. 

‘보기’ 버튼을 클릭하면 Person 객체의 Name, ID 필드를 이용해 

 

아래와 같은 메시지 박스가 뜬다. 

이때 TPerson 클래스의 인스턴스가 생성되지 않았다면

 ‘Access violation’ 에러 메시지가 나타날 것이다 

아래. 마찬가지로 ‘생성’ 버튼을 클릭한 후, ‘해제’ 버튼을 클릭하면 생성되었던 

TPerson 클래스의 인스턴스가 파괴되므로, 

이 때 ‘대입’, ‘보기’ 버튼을 클릭하면 역시 ‘Access violation’ 에러가 발생한다.

에디트 박스 이름과 ID(ttolttol)를 입력한 후

‘생성’, ‘대입’, ‘보기’ 버튼을 클릭하면 나타나는 메시지 박스

Create 하지 않았거나, Free를 호출한 후 ‘대입’, ‘보기’ 버튼을 클릭해서 인스턴스에 접근하려 하면 이와 같은 에러 메시지가 나타난다.



3편계속...

728x90
반응형

댓글