개념 이해
유닛끼리 서로 의존하고 참조할 수 있습니다. 한 유닛이 다른 유닛을 참조할 때 참조 대상 유닛은 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를 참조하는 양방향 순환 구조는 컴파일러가 완전히 지원합니다.