유닛 간 상호 참조

개념 이해

유닛끼리 서로 의존하고 참조할 수 있습니다. 한 유닛이 다른 유닛을 참조할 때 참조 대상 유닛은 interface 인터페이스 구간에 적거나 오직 implementation 구현 구간에 적을 수 있으며 두 방식의 차이는 다음과 같습니다.

interface에 작성 (인터페이스 구간 참조) 참조된 유닛의 내용을 기반으로 외부에 공개되는 새로운 요소(프로시저, 사용자 정의 타입 등)를 정의할 수 있으며 프로젝트 내 모든 다른 유닛에서 접근 가능합니다.

오직 implementation에 작성 (구현 구간 참조) 사용 범위가 제한됩니다. 참조 대상 유닛의 식별자는 현재 유닛의 구현 코드 내에서만 사용할 수 있고 외부에서는 접근할 수 없습니다.

예시

아래 코드는 단순 시연용이며 독자는 아직 클래스(class)를 배우지 않았으므로 개념만 파악하면 됩니다.

새 유닛 파일 Classes.pas를 추가합니다

unit Classes;
{$mode objfpc}{$H+}
interface
type
  TObject=class;
  TComponent=class(TObject)
    constructor Create(AOwner:TComponent);virtual;
  end;
  TObject=class
    destructor Destroy;virtual;
  end;
implementation
constructor TComponent.Create(AOwner:TComponent);begin end;
destructor TObject.Destroy;begin end;
end.

그 후 AnotherUnit.pas 유닛에서 참조를 선언합니다

unit AnotherUnit;
{$ifdef FPC} {$mode objfpc}{$H+}{$J-} {$endif}

interface
uses
  Classes;
// TComponent 클래스는 Classes 유닛에 정의되므로 인터페이스 구간에 Classes를 참조해야 합니다
procedure DoSomethingWithComponent(var C: TComponent);

implementation
uses SysUtils; // SysUtils는 오직 구현 구간에서 참조

procedure DoSomethingWithComponent(var C: TComponent);
begin
  // FreeAndNil은 SysUtils에서 제공하며 구현 코드 내에서만 호출하므로 implementation 구간에만 참조하면 충분합니다
  FreeAndNil(C);
end;

end.Code language: JavaScript (javascript)

주의사항

1 인터페이스 구간에서 양방향 순환 의존 금지

두 유닛이 각자의 interface 구간에서 서로를 동시에 참조하는 행위는 허용되지 않습니다.

원리: 컴파일러가 유닛 인터페이스를 분석할 때 해당 유닛의 uses 인터페이스 목록에 적힌 모든 의존 유닛을 먼저 완전히 분석해야 합니다. 파스칼은 이 규칙을 엄격히 준수하며 두 가지 큰 장점을 제공합니다.

컴파일 속도가 더 빠름; 컴파일러가 재컴파일이 필요한 유닛을 자동 판단하므로 복잡한 Makefile 빌드 스크립트를 수동 관리할 필요가 없습니다. 코드 수정 후 전체 프로젝트를 재컴파일하지 않아도 모든 의존 항목이 동기화되어 갱신됩니다.

2 구현 구간에서는 순환 의존 허용

최소한 한쪽이 상대방 유닛을 오직 implementation 구현 구간에서 참조한다면 순환 의존은 합법적인 코드입니다.

예: 유닛 A는 인터페이스 구간에서 유닛 B를 참조하고 유닛 B는 오직 구현 구간에서 유닛 A를 참조하는 양방향 순환 구조는 컴파일러가 완전히 지원합니다.

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다