ユニットの循環参照

あるユニット内から、別のユニットで定義されているクラスや関数などを参照する場合には、use 節 を利用する事がわかりました(詳しくは、use 節, interface 部, implementaton 部を参照してください)。

ユニット内で uses 節を記述する場合、それは interface 部、及び implementation 部の 2 箇所で記述できます。

interface 部、implementation 部とで記述される uses 節では何が異なるか

まず uses 節とは、単に参照したいユニットを指定するために記述するものだということを留めて置いてください。そして、uses 節で参照したいユニットを指定しても、その参照される側の implementation 部は参照できません。interface 部のみ参照できるだけです。

uses 節は、interface 部, implementation 部の両方で記述できます(interface, implementation の両方で同じユニットを指定することは出来ません)。一つのユニット内で, interface 部, implementation 部の両方に uses 節があっても構いません。では、これらの違いは一体なんでしょうか。

これは、単にスコープの問題です。ユニット A の interface 部の uses 節でユニット B を指定した場合を考えてみます。

この場合、ユニット A の interface、implementation 部でユニット B (の interface 部)を参照できます。

ユニット A の implementation 部の uses 節でユニット B を指定した場合には、ユニット A の implementation 部でユニット B (の interface 部)を参照できます。

以上を, 実際にコードで見てみましょう。

interface 部の uses 節で参照したいユニットを指定した場合

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, MyUnit; // MyUnit を指定

type
  TForm1 = class(TForm)
  private
    { Private 宣言 }
  public
    { Public 宣言 }
  end;

 /////////////  MyUnit の interface 部を参照できる ///////////////

var
  Form1: TForm1;

implementation

{$R *.dfm}

 /////////////  MyUnit の interface 部を参照できる ////////////////

end.

implementation 部の uses 節で参照したいユニットを指定した場合

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs;

type
  TForm1 = class(TForm)
  private
    { Private 宣言 }
  public
    { Public 宣言 }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

uses MyUnit; // MyUnit を指定

 /////////////  MyUnit の interface 部を参照できる ////////////////

end.

つまり、ユニット MyUnit (の interface 部)で定義されているクラスや関数を利用する側のユニットの interface 部で利用したいなら、interface 部の uses 節に記述し、 implementation 部のみで、MyUnit (の interfaec 部)を参照したいなら implementaion 部の uses 節 に記述するということです。

以上をまとめます。

あるユニット A からユニット B で定義されているクラスや関数を参照したい場合、ユニット A のどこで利用したいのか、つまり、interface 部で利用したいのか、それとも implementation 部で利用したいかによって、uses 節をどこに記述するかが、決定されます。

ユニット A の interface 部で, ユニット B を参照したい
ユニット A の interface 部の uses 節で, ユニット B を指定する。
ユニット A の implementation 部のみでユニット B を参照したい
ユニット A の implementation 部の uses 節で, ユニット B を指定する。
ユニット A の interface, implementation 部両方で ユニット B を参照したい
ユニット A のinterface 部の uses 節で、ユニット B を指定する。

interface 部の uses 節で参照したいユニットを指定した場合、利用するユニットのinterface 部、及び implementation 部の両方で、uses 節で指定したユニットを参照できます。

また、一つのユニット内の interface 部、及び implementation 部両方で、同じユニットを指定することは出来ません。

ユニットの循環参照とはなにか

ユニットの循環参照とは、2 つのユニットが互いに interface 部の uses 節で相手のユニットを指定しあっている場合を指します。

ユニットの循環参照が起こっている場合、コンパイルすることが出来ません。ですから、これを回避する必要があります。

ユニットの循環参照を避けるには

ユニットの循環参照を避ける一般的な手法は、循環参照が発生しているユニットのどちらかが implementation 部の uses 節で、相手のユニットを指定するようにする方法です。

循環参照は、お互いのユニット内の interface 部で相手のユニットを参照しあっていることで発生する問題です。ですから、どちらか一方のユニットが、interface 部の uses 節で指定しているユニットを、implementation 部の uses 節に移動させることによって、この問題を回避する事が出来ます。

まとめ


up next
Last update: 2003/9/24