言語
日本語
English

Caution

お使いのブラウザはJavaScriptが無効になっております。
当サイトでは検索などの処理にJavaScriptを使用しています。
より快適にご利用頂くため、JavaScriptを有効にしたうえで当サイトを閲覧することをお勧めいたします。

Pascal辞典

  1. トップページ
  2. Pascal辞典
  3. UNIT(モジュール)の基本

UNIT(モジュール)の基本

『Pascal』の UNIT は、関連する型・定数・変数・手続き・関数をひとまとめにしたモジュールです。INTERFACE セクションで外部に公開するシンボルを宣言し、IMPLEMENTATION セクションで実装を記述します。INITIALIZATION セクションを使うとプログラム起動時に自動実行されるコードを書けます。USES 節に UNIT 名を列挙するだけで再利用でき、大規模プログラムの分割管理に役立ちます。

構文

{ -----------------------------------------------
  UNIT の基本構造
  ----------------------------------------------- }

unit ユニット名;

{ -----------------------------------------------
  INTERFACE セクション — 外部に公開する宣言を書きます
  ----------------------------------------------- }
interface

uses
  依存ユニット名1, 依存ユニット名2;  { 他のユニットへの依存(省略可)}

const
  公開定数名 = 値;

type
  公開型名 = ...;

var
  公開変数名 : 型;

{ 手続き・関数はヘッダーのみ宣言します(実装は IMPLEMENTATION に書く)}
procedure 公開手続き名(引数 : 型);
function  公開関数名(引数 : 型) : 戻り値の型;

{ -----------------------------------------------
  IMPLEMENTATION セクション — 実装を記述します
  ----------------------------------------------- }
implementation

uses
  実装専用の依存ユニット名;  { INTERFACE に不要な依存はここに書きます }

{ 非公開の内部定数・変数・手続き・関数はここで定義します }
const
  内部定数名 = 値;

procedure 公開手続き名(引数 : 型);
begin
  { 処理内容 }
end;

function 公開関数名(引数 : 型) : 戻り値の型;
begin
  { 処理内容 }
  公開関数名 := 戻り値;
end;

{ -----------------------------------------------
  INITIALIZATION セクション(省略可)
  — プログラム起動時に一度だけ実行されます
  ----------------------------------------------- }
initialization
  { 初期化処理 }

{ -----------------------------------------------
  FINALIZATION セクション(省略可)
  — プログラム終了時に一度だけ実行されます
  ----------------------------------------------- }
finalization
  { 後片付け処理 }

end.

構文一覧

構文 / キーワード概要
unit ユニット名;UNIT ファイルの先頭に書くキーワードです。ファイル名(拡張子なし)とユニット名を一致させる必要があります。
interface外部に公開するシンボル(型・定数・変数・手続き・関数のヘッダー)を宣言するセクションの開始です。
implementation手続き・関数の実装本体と、非公開の内部定義を記述するセクションの開始です。
initializationプログラム起動時に一度だけ実行されるコードブロックです。省略できます。グローバル変数の初期化などに使います。
finalizationプログラム終了時に一度だけ実行されるコードブロックです。省略できます。リソースの解放などに使います。
uses ユニット名;依存する UNIT を宣言します。interface セクションと implementation セクションの両方に書けます。
公開と非公開interface に書いたシンボルが公開されます。implementation 内だけで定義したシンボルはそのユニット内専用の非公開となります。
ファイル名の規則Free Pascal では UNIT 名をファイル名(小文字)に合わせる慣習があります(例: unit EvaUnit;evaunit.pas)。

サンプルコード

eva_pilots.pas(UNIT ファイル)
{ eva_pilots.pas — エヴァンゲリオンのパイロット情報を管理する UNIT です }
{
  このファイルは単体ではコンパイルしません。
  メインプログラム eva_main.pas から uses で参照します。
}

unit eva_pilots;

{ -----------------------------------------------
  INTERFACE セクション
  — 外部(メインプログラム)に公開するシンボルを宣言します
  ----------------------------------------------- }
interface

{ パイロットのステータスを表す列挙型(公開)}
type
  TPilotStatus = (
    statusActive,    { 現役パイロット }
    statusInjured,   { 負傷・休養中 }
    statusMissing    { 行方不明 }
  );

{ パイロット 1 人分のデータを格納するレコード型(公開)}
  TPilot = record
    name          : string[40];  { パイロット名 }
    unit_number   : Integer;     { 搭乗 Eva 号機番号 }
    sync_rate     : Real;        { シンクロ率(%)}
    status        : TPilotStatus;{ 現在のステータス }
  end;

{ パイロット数の定数(公開)}
const
  PILOT_COUNT = 5;

{ パイロット情報を表示する手続きのヘッダー(公開)}
procedure PrintPilot(const p : TPilot);

{ シンクロ率の平均を返す関数のヘッダー(公開)}
function  AverageSyncRate(const pilots : array of TPilot) : Real;

{ -----------------------------------------------
  IMPLEMENTATION セクション
  — 手続き・関数の実装本体と、非公開の内部定義を記述します
  ----------------------------------------------- }
implementation

{ ステータスを文字列に変換する非公開ヘルパー関数
  — interface に宣言していないため外部からは呼び出せません }
function StatusToStr(s : TPilotStatus) : string;
begin
  case s of
    statusActive  : StatusToStr := 'Active';
    statusInjured : StatusToStr := 'Injured';
    statusMissing : StatusToStr := 'Missing';
  end;
end;

{ PrintPilot の実装 — パイロット情報を整形して標準出力に書き出します }
procedure PrintPilot(const p : TPilot);
begin
  WriteLn('  Unit-', p.unit_number, '  ', p.name);
  Write  ('    Sync Rate : ');
  WriteLn(p.sync_rate:0:1, '%');
  WriteLn('    Status    : ', StatusToStr(p.status));
end;

{ AverageSyncRate の実装 — アクティブなパイロットのシンクロ率平均を返します }
function AverageSyncRate(const pilots : array of TPilot) : Real;
var
  total : Real;
  count : Integer;
  i     : Integer;
begin
  total := 0.0;
  count := 0;
  { Low/High でオープン配列の添え字範囲を取得します }
  for i := Low(pilots) to High(pilots) do begin
    if pilots[i].status = statusActive then begin
      total := total + pilots[i].sync_rate;
      Inc(count);
    end;
  end;
  if count > 0 then begin
    AverageSyncRate := total / count;
  end else begin
    AverageSyncRate := 0.0;
  end;
end;

{ -----------------------------------------------
  INITIALIZATION セクション
  — プログラム起動時に一度だけ実行されます
  ----------------------------------------------- }
initialization
  WriteLn('[eva_pilots unit] UNIT が初期化されました。');

{ -----------------------------------------------
  FINALIZATION セクション
  — プログラム終了時に一度だけ実行されます
  ----------------------------------------------- }
finalization
  WriteLn('[eva_pilots unit] UNIT が終了処理を実行しました。');

end.
eva_main.pas(メインプログラム)
{ eva_main.pas — eva_pilots UNIT を uses して利用するメインプログラムです }
{
  コンパイルと実行:
    fpc eva_main.pas && ./eva_main
  (eva_pilots.pas が同じディレクトリにある必要があります)
}

program eva_main;

{ -----------------------------------------------
  eva_pilots UNIT を使用宣言します
  — INTERFACE で公開された型・定数・手続き・関数が使えます
  ----------------------------------------------- }
uses
  eva_pilots;

var
  pilots : array[1..PILOT_COUNT] of TPilot;
  i      : Integer;
  avg    : Real;

begin
  { -----------------------------------------------
    パイロットデータを設定します
    ----------------------------------------------- }

  { 碇シンジ(Shinji Ikari)— 初号機パイロット }
  pilots[1].name        := 'Shinji Ikari';
  pilots[1].unit_number := 1;
  pilots[1].sync_rate   := 400.0;   { S2 機関覚醒時の推定値 }
  pilots[1].status      := statusMissing;

  { 綾波レイ(Rei Ayanami)— 零号機パイロット }
  pilots[2].name        := 'Rei Ayanami';
  pilots[2].unit_number := 0;
  pilots[2].sync_rate   := 61.2;
  pilots[2].status      := statusActive;

  { 惣流・アスカ・ラングレー(Asuka Langley Soryu)— 弐号機パイロット }
  pilots[3].name        := 'Asuka Langley Soryu';
  pilots[3].unit_number := 2;
  pilots[3].sync_rate   := 102.0;
  pilots[3].status      := statusInjured;

  { 鈴原トウジ(Toji Suzuhara)— 参号機(代理)パイロット }
  pilots[4].name        := 'Toji Suzuhara';
  pilots[4].unit_number := 3;
  pilots[4].sync_rate   := 23.5;
  pilots[4].status      := statusInjured;

  { 渚カヲル(Kaworu Nagisa)— 第 17 使徒 / Eva パイロット }
  pilots[5].name        := 'Kaworu Nagisa';
  pilots[5].unit_number := 2;   { 弐号機への搭乗 }
  pilots[5].sync_rate   := 99.9;
  pilots[5].status      := statusMissing;

  { -----------------------------------------------
    パイロット情報を一覧表示します
    — PrintPilot は eva_pilots UNIT で定義されています
    ----------------------------------------------- }
  WriteLn('========================================');
  WriteLn('  NERV Evangelion Pilots Report');
  WriteLn('========================================');
  for i := 1 to PILOT_COUNT do begin
    PrintPilot(pilots[i]);
    WriteLn('');
  end;

  { -----------------------------------------------
    アクティブなパイロットのシンクロ率平均を求めます
    — AverageSyncRate は eva_pilots UNIT で定義されています
    ----------------------------------------------- }
  avg := AverageSyncRate(pilots);
  WriteLn('Active Pilots Average Sync Rate : ', avg:0:1, '%');
  WriteLn('========================================');
end.
fpc eva_main.pas && ./eva_main
Free Pascal Compiler version ...
Compiling eva_pilots.pas
Compiling eva_main.pas
Linking ./eva_main
[eva_pilots unit] UNIT が初期化されました。
========================================
  NERV Evangelion Pilots Report
========================================
  Unit-1  Shinji Ikari
    Sync Rate : 400.0%
    Status    : Missing

  Unit-0  Rei Ayanami
    Sync Rate : 61.2%
    Status    : Active

  Unit-2  Asuka Langley Soryu
    Sync Rate : 102.0%
    Status    : Injured

  Unit-3  Toji Suzuhara
    Sync Rate : 23.5%
    Status    : Injured

  Unit-2  Kaworu Nagisa
    Sync Rate : 99.9%
    Status    : Missing

Active Pilots Average Sync Rate : 61.2%
========================================
[eva_pilots unit] UNIT が終了処理を実行しました。

finalization セクションの出力は FPC のバージョンによって表示されない場合があります。FPC 3.2.2 では表示されないことが確認されています。

よくあるミス

IMPLEMENTATION セクションで INTERFACE の宣言を重複して書く

IMPLEMENTATION セクションでは、手続き・関数の実装本体だけを書きます。INTERFACE に書いたヘッダ宣言(引数リストや戻り値型)を IMPLEMENTATION でも完全に重複させる必要はなく、手続き名のみで定義できます。Free Pascal では引数リストを省略した短縮形が認められています。

unit_impl_note.pas
unit unit_impl_note;

interface
  procedure Greet(const name: string);

implementation

{ 省略形: 引数リストを省略できます(Free Pascal 拡張) }
procedure Greet;
begin
  { name はスコープ内で参照できます }
end;

end.

UNIT ファイル名と unit 宣言名を一致させない

Free Pascal では、ファイル名(拡張子なし)と unit 宣言に書いた名前は一致させる必要があります。一致しない場合はコンパイルエラーになります。

mymodule.pas(NG: ファイル名が mymodule なのに unit 宣言が別名)
unit OtherName;  { NG: ファイル名 mymodule と一致しない }

interface
implementation
end.
Fatal: Unit name "OtherName" does not match filename "mymodule"

ファイル名と unit 宣言を一致させます。

mymodule.pas(OK)
unit mymodule;  { ファイル名と一致させます }

interface
implementation
end.

概要

『Pascal』の UNIT はプログラムをファイル単位で分割するモジュール機構です。INTERFACE セクションに外部公開するシンボルを宣言し、IMPLEMENTATION セクションに実装を隠蔽することで、カプセル化と再利用性を実現できます。INITIALIZATIONFINALIZATION を使えばリソースの初期化・後片付けをモジュール内で自己完結させることができます。UNIT 内で定義した型をレコード型として使う詳しい使い方は RECORD(レコード型の基本) を、手続き・関数の定義の基礎は PROCEDURE(手続きの定義) および FUNCTION(関数の定義) を合わせて確認してください。

記事の間違いや著作権の侵害等ございましたらお手数ですがまでご連絡頂ければ幸いです。