1. オブジェクト指向拡張と標準 Pascal のレコード型
当記事で書かれている "オブジェクト指向拡張" と "Object Pascal" の定義を先に述べておきます。そしてオブジェクト指向拡張と密接な関係にある Pascal のレコード型についても触れておきます。
1.1. オブジェクト指向拡張
初期は Borland、現在では Embarcadero が開発している Delphi が採用している言語はオブジェクト指向言語である Object Pascal です。
「何をもってオブジェクト指向言語なのか?」というのはとても難しい問いだとは思うのですが、オブジェクト指向プログラミングの三原則である カプセル化
、 継承
、 多態性
が行える "クラスまたはその類似機能" を備えていれば "オブジェクト指向 (プログラミングが可能な) 言語" と言えると思います。
何をもって Object Pascal なのか?という問いに対しては、Apple の Object Pascal に沿った実装になっていれば Object Pascal と言えると思います。
途中で Borland が 「Delphi の言語は Delphi 言語」と言い出した事もありましたが「Pascal って古臭いイメージが付いて回ってるからとりあえず言語名から Pascal 抜いとこ」とかいう判断だったのだと思います、多分 1。
1.2. 標準 Pascal のレコード型
Pascal には初期 2 から構造化型の一つとしてレコード型があります。
詳細はリンク先の記事に譲るとして、簡単に言えば他言語で言うところの構造体です。Pascal のレコード型には可変部があり、可変部だけ見ると共用体でもあります。
複数の型を持つ要素を含められるため、クラスを実装するにはレコードを拡張するのが最も都合がよく、実際 Object Pascal のクラスはレコードを拡張した形で行われています。
1.2.1. (静的な) レコード
レコード型は型宣言部 (type) にて "型名 = record ~ end;" で定義します。変数宣言部 (var) でレコード型の変数を宣言すれば (静的な) レコードを使うことができます。
program RecordTest1(Output);
type
TRec = record { レコード型の定義 }
ID: Integer;
FirstName: packed array [1..20] of Char;
LastName: packed array [1..20] of Char;
end;
var
Rec: TRec; { レコード型変数の宣言 }
begin
Rec.ID := 100;
Rec.FirstName := 'Hello, ';
Rec.LastName := 'world. ';
writeln(Rec.ID );
writeln(Rec.FirstName);
writeln(Rec.LastName );
end.
上記例の場合、Rec は TRec 型の (静的な) 変数です。標準 Pascal の用語で詳細を説明すると次のようになります。
識別子 | 意味 |
---|---|
TRec | レコード型 |
Rec | TRec 型の (静的な) 変数 |
- 型定義部 (type) で TRec というレコード型が定義されている。
- 変数宣言部 (var) で Rec という TRec レコード型が宣言されている。
ここでは後述する 動的な変数
の対比の意味で (静的な) 変数
と呼んでいますが、静的変数と呼んでしまうと別の意味になってしまうので注意が必要です 3。
1.2.2. 動的なレコード
動的なレコードを使うには、定義したレコード型のポインタ型を定義し、New() で新しい動的レコード型変数を作成し、Dispose() で動的レコード型変数用に割り当てられたメモリを解放します。
program RecordTest2(Output);
type
TRec = record { レコード型の定義 }
ID: Integer;
FirstName: packed array [1..20] of Char;
LastName: packed array [1..20] of Char;
end;
PRec = ^TRec; { ポインタ型の定義 }
var
Rec: PRec; { ポインタ型変数の宣言 }
begin
New(Rec); { 動的変数用メモリの確保と識別値の割り当て }
{ 動的変数を逆参照してアクセス }
Rec^.ID := 100;
Rec^.FirstName := 'Hello, ';
Rec^.LastName := 'world. ';
writeln(Rec^.ID );
writeln(Rec^.FirstName);
writeln(Rec^.LastName );
Dispose(Rec); { 識別値が指す動的変数用メモリの解放 }
end.
上記例の場合、Rec は TRec 型のポインタ変数で、Rec^ のようにキャレット記号 (^) を使って動的変数を逆参照しています。標準 Pascal の用語で詳細を説明すると次のようになります。
識別子 | 意味 |
---|---|
TRec | レコード型 (対象型) |
PRec | ポインタ型 |
Rec | ポインタ型変数 |
Rec^ | TRec 型の動的変数 (対象変数) |
- 型定義部 (type) で TRec というレコード型が定義されている。
- 型定義部 (type) で TRec を対象型とするポインタ型 PRec が定義されている。
- 変数宣言部 (var) で Rec という PRec ポインタ型が宣言されている。
- New() で TRec 型の動的変数 (対象変数) 用メモリが確保され、動的変数を指し示す識別値 (ポインタ値) がポインタ型変数 Rec に格納される。
- ポインタ型変数 Rec に格納されている識別値 (ポインタ値) から動的変数 (対象変数) を逆参照するには Rec^ のようにキャレット記号 (逆参照演算子) を使う。
- Rec に格納されている識別値 (ポインタ値) が指し示す TRec 型の動的変数 (対象変数) が使っていたメモリは Dispose() で解放される。
Delphi では古いバージョンを除いて、逆参照演算子を省略できます 4。
参考文献
タイトル | 著者 | ISBN-10 (Amazon) |
出版年 |
---|---|---|---|
PASCAL 原書第 4 版 | キャスリン・イェンゼン (著) ニクラウス・ヴィルト (著) アンドリュー・B・ミケル (編) ジェームス・F・マイナー (編) 原田 賢一 (訳) |
4563014664 | 1993/10/30 |
標準 Pascal についてはこの本で大体理解できます。オススメ。
See also:
- 『PASCAL』 - Wirth 先生の邦訳本を読んでみる (Qiita)
- 培風館の Pascal 関連書籍を読んでみる (Qiita)
- 標準 Pascal の規格票と解説書を読んでみる (Qiita)
- 標準 Pascal 範囲内での Delphi 入門 (Qiita)
索引
[ ↑ 目次へ ] [ → 2. Clascal のオブジェクト指向拡張 ]
-
Borland の中の人、あまり深く考えてなかったと思うよ。 ↩
-
Pascal は 1970 年に発表 (リリース) されています。 ↩
-
Delphi での静的変数については 標準 Pascal 範囲内での Delphi 入門 - (3.3.2.) 型付きの定数 (Typed Constants) を参照。 ↩
-
Delphi 2 以降で(動的)レコード型の逆参照演算子が省略できます。 ↩