このブログはLazarus(FreePascal)アドベントカレンダー23日目の記事です。
今回の内容はPascalのデータ型について。
Pascalのデータ型はちょっと特徴的で(といっても、最近PythonやJavaScriptなど明確に型のない言語しかつかってないのでどれだけ特殊なのかは分からないのですが)、いくつかの種類のデータ型があります。
- クラス型
- 構造体型
- プリミティブ型
- 配列型
- ポインタ型
- 関数型(関数のポインタ型)
- メソッド型(メソッドのポインタ型)
特に注意が必要なデータ型いろいろ
プリミティブ型の扱い
プリミティブ型だけみても結構な種類があり、数値だけでもInteger、Cardinal型、DWord型、QWord型、UInt型などいろいろな型があります。
基本的にはOSのビット数などで定義が切り替わるInteger型かCardinal型あたりを使うのが安全 ということだったと思いますが(Delphiのときには)、型を指定してデータ型を要求してきたり、戻り値が指定されたりすることもあり、実質おなじデータ型でも型が違うと引数に指定できない場合があるので、そういうものだくらいは覚えておいた方がいいです。
LCLオブジェクトなどのCaption
プロパティの型であるTCaption
も、辿っていけばString型です。先日ちょっと触れたヘルパークラスメソッドも、使うことができます。
これらはLazarusのソースエディタ上でデータ型にカーソルを合わせるか、Ctrlキーを押しながらクリックすることで、大元となっているデータ型を知ることができます。正直この辺はぱっと見分かりづらいので気になったら調べておくと良さそう。
また、Windows APIやOLEオブジェクトにデータ型を引き渡すときはPCharやPWCharなどのデータ型を指定する必要があります。これはポインタ型ではありますが、文字列型をキャストすることで作成できます。
uses Windows…; {中略} procedure TForm1.FormCreate(Sender: TObject); begin SetWindowText(Self.Handle, PChar('TEST')); end;
クラス型
また、Pascalにはガベージコレクションがありませんので、クラス型の場合データの解放処理が必要となります(Object.Free
メソッド)。Pythonを使ってる身からすると「withでいいやん」くらいに思ってしまうのですが、そういう便利構文はないようです。
constructor TLocalizer.Create; var r: TResourceStream; begin FLanguage:='def'; r := TResourceStream.Create(HINSTANCE, 'LANG', RT_RCDATA); try FLocalizeFile := TMemIniFile.Create(r, []); finally r.Free; end; end;
なお、クラス型以外のデータはスコープから抜けた時点で解放されるのでメモリの解放処理は必要ありません。
配列型
Pascalでは関数が特定の型の配列を返すときなどは、配列型の定義が必要です。
type TIntArray= array of Integer; function Test: TIntArray; begin Result:=[1,2]; end; begin WriteLn(Test[0]); // -> 1 ReadLn; end.
ただし、開発環境が結構よろしくガイドを表示してくれるので…。
しかしそこはさすが静的型付け言語。Lazarusが結構適切にデータ型の情報を表示してくれるので、それほどには迷わなかったりします。
PythonやJavaScriptだとそうもいかないのでここは「さすがPascal…」と思ってしまいます(まあ他の言語でも静的型付け言語ならそんなもんだとは思いますが)。
とはいえ分かりづらい部分があるのに変わりはないので、マウスホバー時のヒントやCtrl+Spaceキーなどで表示されるインテリセンスなどを上手く活用したコーディングをしていきましょう。