지난 시간에 델파이의 클래스에 대해서 정리했다. 클래스는 재사용이 가능하다는 장점이 있고, 상속이라는 특징을 가지고 있다. 상속 관련된 몇 가지 키워드가 있는데, 오늘은 그 키워드들을 정리해보고자 한다.
먼저 Virtual은 부모 클래스에서 상속가능한 것임을 명시하는데 사용된다.
자식클래스에서는 Override키워드를 통해 재정의하거나 해당 기능을 사용하는 것을 의미하며
Inherited는 Override를 통해 재정의를 하는 도중에 부모의 기능을 그대로 사용하고자 하는 부분에 쓴다.
Reintroduce는 상속받았지만 부모의 기능을 사용하지 않는다는 의미를 가진다.
음. 말로 써놓으니 하나도 모르겠군. 찬찬히 다시 한 번 보자.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | type TIntroduce = class procedure WhoIAm; virtual; end; TChildIntroduce = class(TIntroduce) procedure WhoIAm; override; end; procedure TIntroduce.WhoIAm; begin TempMemo.Lines.Add('I AM TIntroduce'); end; procedure TChildIntroduce.WhoIAm; begin inherited; TempMemo.Lines.Add('I AM TChildIntroduce'); end; //procedure TChildIntroduce.WhoIAm; //begin // TempMemo.Lines.Add('I AM TChildIntroduce'); // // inherited; //end; | cs |
1 2 3 4 5 6 7 8 9 10 11 12 | procedure TIntroduce.WhoIAm; begin TempMemo.Lines.Add('I AM TIntroduce'); end; procedure TChildIntroduce.WhoIAm; begin inherited; TempMemo.Lines.Add('I AM TChildIntroduce'); end; | cs |
<코드B>
1 2 3 4 5 6 7 8 9 10 11 | procedure TIntroduce.WhoIAm; begin TempMemo.Lines.Add('I AM TIntroduce'); end; procedure TChildIntroduce.WhoIAm; begin TempMemo.Lines.Add('I AM TIntroduce'); TempMemo.Lines.Add('I AM TChildIntroduce'); end; | cs |
<코드C>
위의 <코드B>와 <코드C>는 같은 의미의 코드가 된다.
그럼 다시 <코드A>로 돌아가보자. 16라인과 24라인의 WhoIAm함수는 각각 어떻게 TempMemo에 출력이 될까. 먼저 16라인의 WhoIAm함수는 inherited로 부모 클래스의 해당 함수(TIntroduce.WhoIAm)를 호출하고나서 자신의 함수(TChildIntroduce.WhoIAm)를 호출하게 되므로
1 2 | I AM TIntroduce I AM TChildIntroduce | cs |
1 2 | I AM TChildIntroduce I AM TIntroduce | cs |
여기까지는 무리없이 이해가 되었겠지! 그럼 Override와 Reintroduce에 대해 알아보자.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | type TIntroduce = class procedure Create; end; TChildIntroduce1 = class(TIntroduce) procedure Create; override; end; TChildIntroduce2 = class(TIntroduce) procedure Create; reintroduce; end; procedure TIntroduce.Create; begin TempMemo.Lines.Add('I AM TIntroduce'); end; procedure TChildIntroduce1.Create; begin TempMemo.Lines.Add('I AM Chiled1'); end; procedure TChildIntroduce2.Create; begin TempMemo.Lines.Add('I AM Chiled2'); end; procedure Test; var aIntro1 : TIntroduce; aIntro2 : TIntroduce; begin aIntro1 := TChildIntroduce1.Create; aIntro2 := TChildIntroduce2.Create; end; | cs |
<코드X>
오...코드가 너무 길지만 알고나면 너무 쉬운 소스니까 걱정말고 계속 읽어도 된다. 뒤로가기 없기~
우선 보면 TChildIntroduce1, 2는 TIntroduce를 상속받아서 생성한 클래스이다. 그리고 TChildIntroduce1은 상속받은 Create함수에 override키워드를, TChildIntroduce2는 reintroduce 키워드를 사용하였고, Test프로시저에서 aIntro1과 2를 TIntroduce 자료형으로 선언한 뒤에, 각각 TChildIntroduce1과 2로 Create해주었다.
어떤 메시지를 출력하게 될까?
구글링을 좀 해본 사람은 바인딩(Binding)이라는 용어를 종종 보았을 것이다. override는 binding이 가능해서 자식의 메소드를 사용하고, reintroduce는 binding이 되지않아서 부모의 메소드를 사용하게 된다. 이 뜻을 이해하기 쉽게 그림을 준비했다.
쨘! 세상에 단번에 이해가 갈듯. 후후후. 그림은 TParent와 그것을 상속받은 TChild1, TChild2를 나타내고 있다. TParent자료형으로 변수를 선언한 경우 노란색으로 표시한 부분(부모의 영역)만 접근하여 사용이 가능하게 된다. 그러나 TChild1의 경우 override를 이용해서 자식의 영역에 접근하여 자식의 선언을 이용할 수 있게 된다. 이것을 binding이라고 하는 것이다! 그럼 오른쪽의 TChild2의 경우 당연히 reintroduce로 선언한 것으로, binding이 되지 않기 때문에 자식의 영역에 접근이 불가능하며, 부모의 것을 그대로 사용하게 된다.
그럼 다시 <코드X>로 돌아가보자. aIntro1과 aIntro2는 똑같이 TIntroduce 자료형으로 선언되었다. 그리고 각각 TChildIntroduce1과 TChildIntroduce2로 객체가 생성되었다. aIntro1의 경우 override로 정의된 TChildIntroduce1으로 객체를 생성하였으므로, TIntroduce로 선언하였지만 자식의 영역에 접근이 가능할 것이고,
1 | I AM Child1 |
위와 같이 "I AM Child1"이라는 문구를 출력하는 자식의 Create문을 실행할 것이다.
반면에 aIntro2의 경우 reintroduce로 정의된 TChildIntroduce2로 객체를 생성하였으므로, 자식의 영역에 접근이 불가능하게 된다. 그러므로
1 | I AM TIntroduce | cs |

'노동자의 삶 > 델파이' 카테고리의 다른 글
델파이 - 그리드에 체크박스가 안 나올 경우 (0) | 2018.07.27 |
---|---|
델파이의 클래스(1) - 기본개념 (0) | 2018.04.25 |
델파이에서 디버깅하기 (0) | 2018.04.24 |
델파이에서 Move와 Copy의 차이점 (0) | 2018.04.23 |
델파이 실행오류 - 동시에 두 개의 델파이를 켜고 싶을 때 (0) | 2018.02.27 |