Marco Cantù's
Essential Pascal Chapter 10
Variants
第10章 バリアント
To provide full OLE support, the 32-bit version of Delphi includes the Variant data type. Here I want to discuss this data type from a general perspective. The Variant type, in fact, has a pervasive effect on the whole language, and the Delphi components library also uses them in ways not related to OLE programming.
OLE を完璧にサポートするため、32 ビット・バージョンの Delphi では、バリアント・データ型を導入している。 ごく一般的なことから、始めてみよう。 実際のところ、バリアント型は、言語全体に影響を保っており、Delphi では、OLE プログラミングとは直接関係の無い、コンポーネント・ライブラリでも、使われている。
Variants Have No Type
バリアントは、型を持たない
In general, you can use variants to store any data type and perform numerous operations and type conversions. Notice that this goes against the general approach of the Pascal language and against good programming practices. A variant is type-checked and computed at run time. The compiler won't warn you of possible errors in the code, which can be caught only with extensive testing. On the whole, you can consider the code portions that use variants to be interpreted code, because, as with interpreted code, many operations cannot be resolved until run time. This affects in particular the speed of the code.
一般的には、バリアントは特定のデータ型を持たず、種々の操作や、型変換に用いられる。 もちろん、これは一般的な Pascal 言語の考え方に背くもので、また、良いプログラミング手法にも背いている。 バリアントは、実行時に型チェックされ、計算される。 エラーがあっても、実地にテストしない限り、コンパイラは、そのコード部分では警告を出さない。 つまり、バリアントを使用しているコードは、インタープリタ用コード、と考えるべきだ。 インタープリタ用コードは、実行時にのみ、解釈・実行される、のだから。 これは、そのコード部分のスピードにも影響してしまう。
Now that I've warned you against the use of the Variant type, it is time to look at what it can do. Basically, once you've declared a variant variable such as the following:
さて、バリアントの使用について、警告したから、何ができるか、見てみよう。 一度、下記のようにバリアント型の変数を宣言したら、
var
V: Variant;
you can assign to it values of several different types:
型の違う値を、この変数に格納できる。
V := 10;
V := 'Hello, World';
V := 45.55;
Once you have the variant value, you can copy it to any compatible-or incompatible-data type. If you assign a value to an incompatible data type, Delphi performs a conversion, if it can. Otherwise it issues a run-time error. In fact, a variant stores type information along with the data, allowing a number of run-time operations; these operations can be handy but are both slow and unsafe.
バリアント型の値は、互換性のあるものや、無いものにも代入できる。 もし互換性の無いものに代入した場合は、可能なら、Delphi が変換を行う。 もちろん、実行時エラーは出る。 事実、バリアントは、データにくっつけて型情報を持っており、いくつかの実行時操作ができるようになっている。 こうした操作は、便利ではあるが、実行スピードが遅く、また安全なものではない。
Consider the following example (called VariTest), which is an extension of the code above. I placed three edit boxes on a new form, added a couple of buttons, and then wrote the following code for the OnClick event of the first button:
上のコードを拡張した、サンプル ( VariTest というアプリ) を見て欲しい。 新しいフォームに、Edit を3個乗せ、ボタンをいくつか加え、最初のボタンの OnClick イベントで、このコードを書いた;
procedure TForm1.Button1Click(Sender: TObject);
var
V: Variant;
begin
V := 10;
Edit1.Text := V;
V := 'Hello, World';
Edit2.Text := V;
V := 45.55;
Edit3.Text := V;
end;
Funny, isn't it? Besides assigning a variant holding a string to the Text property of an edit component, you can assign to the Text a variant holding an integer or a floating-point number. As you can see in Figure 10.1, everything works.
面白いだろ? Edit の Text プロパティに、バリアントが保持している文字列を渡す以外に、整数と浮動小数点値も、バリアントを介して Text に渡せる。 図 10.1 で分かるように、どんなものでもOKだ。
Figure 10.1: The output of the VariTest example after the Assign button has been pressed.
図 10.1 : Assign ( 割り当て ) ボタンをクリックした時の VariTest サンプルの出力例
Even worse, you can use the variants to compute values, as you can see in the code related to the second button:
もっと悪いことに、バリアントでは値の計算までできる。 2番目のボタンに付けられたコードを見て欲しい;
procedure TForm1.Button2Click(Sender: TObject);
var
V: Variant;
N: Integer;
begin
V := Edit1.Text;
N := Integer(V) * 2;
V := N;
Edit1.Text := V;
end;
Writing this kind of code is risky, to say the least. If the first edit box contains a number, everything works. If not, an exception is raised. Again, you can write similar code, but without a compelling reason to do so, you shouldn't use the Variant type; stick with the traditional Pascal data types and type-checking approach. In Delphi and in the VCL (Visual Component Library), variants are basically used for OLE support and for accessing database fields.
どう見ても、こういうコードを書くのは、危険すぎる。 もし最初の Edit に数値が入っているときには問題ない。 数値でなければ、例外が発生する。 大切なのは、このようなコードを書いてもいいが、どうしてもそうしなければならない、という時以外は、バリアントを使わないことだ。 伝統的な Pascal データ型を使い、型チェックをしてもらう手法を取るべきだ。 Delphi と VCL ( Visual Component Library ) でもバリアントは使われているが、これは基本的に OLE をサポートするためと、データベースにアクセスするためのものだ。
Variants in Depth
Delphi でのバリアント
Delphi includes a variant record type, TVarData, which has the same memory layout as the Variant type. You can use this to access the actual type of a variant. The TVarData structure includes the type of the Variant, indicated as VType, some reserved fields, and the actual value.
Delphi には、バリアント型のレコード型もある。 TVarData といい、バリアントと同じメモリ配置になっている。 これを使うと、バリアント型そのものにアクセスできる。 TVarData 構造には、VType という形式のバリアント型、予約領域、実値が含まれる。
The possible values of the VType field correspond to the data types you can use in OLE automation, which are often called OLE types or variant types. Here is a complete alphabetical list of the available variant types:
VType フィールドの値は、OLE オートメーションで使える、データ型と一致しており、しばしば OLE 型、またはバリアントと呼ばれる。 可能なバリアント型をアルファベット順に示す。
varArray
varBoolean
varByRef
varCurrency
varDate
varDispatch
varDouble
varEmpty
varError
varInteger
varNull
varOleStr
varSingle
varSmallint
varString
varTypeMask
varUnknown
varVariant
You can find descriptions of these types in the Values in variants topic in the Delphi Help system.
Delphi ヘルプの「バリアント」/値 ( Values ) 項を見れば、上記の型の説明がある。
There are also many functions for operating on variants that you can use to make specific type conversions or to ask for information about the type of a variant (see, for example, the VarType function). Most of these type conversion and assignment functions are actually called automatically when you write expressions using variants. Other variant support routines (look for the topic Variant support routines in the Help file) actually operate on variant arrays.
バリアントを扱う多数の関数があり、この関数は、特別な型変換やバリアントの型情報 ( VarType 関数を見てみるといい ) を得るために使える。 こうした型変換や、割り当て ( Assign ) 関数の多くが、バリアントを使った式を書けば、自動的に呼ばれる。 それ以外のバリアントをサポートするルーチン ( ヘルプのバリアント・サポート・ルーチンの項を参照 ) は、バリアント配列で用いられる。
Variants Are Slow!
バリアントは、遅い!
Code that uses the Variant type is slow, not only when you convert data types, but also when you add two variant values holding an integer each. They are almost as slow as the interpreted code of Visual Basic! To compare the speed of an algorithm based on variants with that of the same code based on integers, you can look at the VSpeed example.
バリアントを使っているコードは、遅い。 これはデータ型を変換する場合だけでなく、それぞれ整数を保持しているふたつのバリアントを加算する場合にも言える。 まるで、Visual Basic 並みだ! バリアントを使うアルゴリズムと、整数のみを使うものを比べてみよう。 VSpeed サンプルを見て欲しい。
This program runs a loop, timing its speed and showing the status in a progress bar. Here is the first of the two very similar loops, based on integers and variants:
このプログラムはループ処理をするもので、スピードを測り、その状態をプログレス・バーに表示する。 整数と、バリアントを使っているが、殆ど同じループになっているコードの内、バリアント用のものを示す。
procedure TForm1.Button1Click(Sender: TObject);
var
time1, time2: TDateTime;
n1, n2: Variant;
begin
time1 := Now;
n1 := 0;
n2 := 0;
ProgressBar1.Position := 0;
while n1 < 5000000 do
begin
n2 := n2 + n1;
Inc (n1);
if (n1 mod 50000) = 0 then
begin
ProgressBar1.Position := n1 div 50000;
Application.ProcessMessages;
end;
end;
// we must use the result 結果を使わなくちゃ
Total := n2;
time2 := Now;
Label1.Caption := FormatDateTime (
'n:ss', Time2-Time1) + ' seconds';
end;
The timing code is worth looking at, because it's something you can easily adapt to any kind of performance test. As you can see, the program uses the Now function to get the current time and the FormatDateTime function to output the time difference, asking only for the minutes ("n") and the seconds ("ss") in the format string. As an alternative, you can use the Windows API's GetTickCount function, which returns a very precise indication of the milliseconds elapsed since the operating system was started.
この時間測定コードは役に立つよ。 パフォーマンスを調べたい時、簡単に使えるね。 見て分かるように、このプログラムでは関数をふたつ使っている。 Now は、現在の時刻を知るため、FormatDateTime は、時間差を表示するために使い、フォーマット文字列の内、分 ("n") と秒 ("ss") のみを使っている。 別のやり方として、Windows API の GetTickCount を使ってもいい。 これは、OSが始動してからの経過時間を、ミリ秒の単位で返すものだ。
In this example the speed difference is actually so great that you'll notice it even without a precise timing. Anyway, you can see the results for my own computer in Figure 10.2. The actual values depend on the computer you use to run this program, but the proportion won't change much.
このサンプルでは、バリアントと整数の処理時間差があまりに大きいので、正確な時間測定の必要も無いくらいだ。 どちらにしても、図 10.2 で、私のコンピュータで実測した結果を見ることができる。 実測値は、このプログラムを走らせるコンピュータによって違うが、この時間差が大きく縮まることは無いだろう。
Figure 10.2: The different speeds of the same algorithm, based on integers and variants (the actual timing varies depending on the computer), as shown by the VSpeed example.
図 10.2 : VSpeed サンプルを実行して示される、同じアルゴリズムでの、整数とバリアントの時間差。 ( 実測値は、コンピュータによって違う )
Conclusion
結論
Variants are so different from traditional Pascal data types that I've decided to cover them in this short separate chapter. Although their role is in OLE programming, they can be handy to write quick and dirty programs without having even to think about data types. As we have seen, this affects performance by far.
バリアントは、伝統的な Pascal データ型と大きく違い、この短い章のみで取り扱った。 バリアントの役目は、OLE プログラミングにあり、データ型に気を使わないで、素早く、しかも汚いプログラムを書くには便利だ。 ただ、その代わり、パフォーマンスが低下する。
Now that we have covered most of the language features, let me discuss the overall structure of a program and the modularization offered by units.
さて、言語の特徴については、ほぼカバーしたから、プログラムの構造と、ユニットが実現するモジュール化について、検討していこう。
Next Chapter: Program and Units
次章 : プログラムとユニット
© Copyright Marco Cantù, Wintech Italia Srl 1995-2000
Marco Cantu's
Essential Pascal Chapter 11
Program and Units
第11章 プログラムとユニット
Delphi applications make intensive use of units, or program modules. Units, in fact, were the basis of the modularity in the language before classes were introduced. In a Delphi application, every form has a corresponding unit behind it. When you add a new form to a project (with the corresponding toolbar button or the File > New Form menu command), Delphi actually adds a new unit, which defines the class for the new form.
Delphi アプリケーションでは、ユニット、またはプログラム・モジュールを使うことが普通になっている。 実のところ、クラスが導入される前は、ユニットがモジュール化の基礎になっていた。 Delphi アプリケーションでは、それぞれのフォームには、その背後に、これに符合するユニットがある。 プロジェクトにフォームを加える ( ツールバーのボタンを使うか、ファイル/フォームの新規作成で ) と、Delphi は新しいユニットを加える。 このユニットには、そのフォームのクラスが定義してある。
Units
ユニット
Although every form is defined in a unit, the reverse is not true. Units do not need to define forms; they can simply define and make available a collection of routines. By selecting the File > New menu command and then the Unit icon in the New page of the Object Repository, you add a new blank unit to the current project. This blank unit contains the following code, delimiting the sections a unit is divided into:
すべてのフォームはユニットにその定義があるが、その逆は無い。 ユニットに必ずフォームを定義する必要は無い。 ルーチンの集まりを定義するだけでも使える。 ファイル/新規作成を選ぶと、オブジェクトリポジトリの新しいページに、ユニット・アイコンが現れ、既存のプロジェクトに、新しいブランクのユニットを追加できる。 このブランクのユニットには、ユニットの構成要素を示す、下記のコードが記されている。
unit Unit1;
interface
implementation
end.
The concept of a unit is simple. A unit has a unique name corresponding to its filename, an interface section declaring what is visible to other units, and an implementation section with the real code and other hidden declarations. Finally, the unit can have an optional initialization section with some startup code, to be executed when the program is loaded into memory; it can also have an optional finalization section, to be executed on program termination.
ユニットのコンセプトは単純だ。 ユニットは、自分のファイル名と同じ名前の、ユニークな名前を持っていて、interface 部には、他のユニットにどういうものを公開するか、定義してあり、implementation 部には、実際のコードと、その他の宣言がある。 これに加えユニットには、プログラムがメモリにロードされた時に実行される、スタートアップ・コードが記述された初期化部を付けても良いし、プログラムの終了時に実行される、終末部を付けても良い。
The general structure of a unit, with all its possible sections, is the following:
各部をすべて列挙した、一般的なユニットの構成は、
unit unitName;
interface
// other units we need to refer to 他のユニットを参照
uses
A, B, C;
// exported type definition エクスポートされる型宣言
type
newType = TypeDefinition;
// exported constants エクスポート定数
const
Zero = 0;
// global variables グローバル変数
var
Total: Integer;
// list of exported functions and procedures エクスポート関数と手続きのリスト
procedure MyProc;
implementation
uses
D, E;
// hidden global variable 隠されたグローバル変数
var
PartialTotal: Integer;
// all the exported functions must be coded エクスポート関数のコード
procedure MyProc;
begin
// ... code of procedure MyProc MyProc 手続きのコード
end;
initialization
// optional initialization part 初期化部(使用は自由)
finalization
// optional clean-up code クリーンアップ・コード(使用は自由)
end.
The uses clause at the beginning of the interface section indicates which other units we need to access in the interface portion of the unit. This includes the units that define the data types we refer to in the definition of other data types, such as the components used within a form we are defining.
interface 部の初めにある uses 節は、ユニットのインターフェイスでアクセスを要する、他のユニットを指している。 この、他のユニットには、フォームの中で定義するコンポーネントと同様に、元のユニットで別のデータ型を使いたいときに用いる、型定義が納められている場合もある。
The second uses clause, at the beginning of the implementation section, indicates more units we need to access only in the implementation code. When you need to refer to other units from the code of the routines and methods, you should add elements in this second uses clause instead of the first one. All the units you refer to must be present in the project directory or in a directory of the search path (you can set the search path for a project in the Directories/Conditionals page of the project痴 Options dialog box).
implementation 節の始めにある、2番目の uses 節には、implementaion 部でアクセスする必要のあるユニットを書く。 ルーチンやメソッドから別のユニットを参照する時は、最初の uses の代わりに、この2番目の uses 節に書いておく。 参照するユニットは、すべて、必ずプロジェクト・ディレクトリ、またはサーチ・パス ( プロジェクト/オプション・ダイアログボックスにある、ディレクトリ/条件ページのプロジェクト・サーチ・パスとして登録しておける ) のディレクトリに無いと、いけない。
C++ programmers should be aware that the uses statement does not correspond to an include directive. The effect of a uses statement is to import just the precompiled interface portion of the units listed. The implementation portion of the unit is considered only when that unit is compiled. The units you refer to can be both in source code format (PAS) or compiled format (DCU), but the compilation must have taken place with the same version of the Delphi.
C++ プログラマには、uses 文が、include 指令とはつながっていないことに、注意して欲しい。 uses 文がすることと言えば、リストにあるユニットの、プリコンパイルされた interface 部をインポートすることだけだ。 ユニットの implementation 部は、そのユニットをコンパイルするときのみ、参照される。 君が参照しているユニットは、ソースコード形式 ( PAS ) にもできるし、コンパイル済みの形式 ( DCU ) にもできる。 ただし、同じバージョンの Delphi でコンパイルしないといけない。
The interface of a unit can declare a number of different elements, including procedures, functions, global variables, and data types. In Delphi applications, the data types are probably used the most often. Delphi automatically places a new class data type in a unit each time you create a form. However, containing form definitions is certainly not the only use for units in Delphi. You can continue to have traditional units, with functions and procedures, and you can have units with classes that do not refer to forms or other visual elements.
ユニットの interface には、手続き、関数、グローバル変数、データ型など、様々な要素を宣言できる。 Delphi アプリなら、データ型を定義しておくのが、一番多いだろう。 フォームを生成する時には、Delphi が自動的に、新しいクラスデータ型をユニットに加える。 しかし Delphi では、ユニットはフォーム定義にのみ使われる、と言うわけでは無い。 関数や手続きだけの、伝統的なユニットも書けるし、フォームやビジュアルな要素を参照しようとしない、クラスだけのユニットも書ける。
Units and Scope
ユニットとスコープ
In Pascal, units are the key to encapsulation and visibility, and they are probably even more important than the private and public keywords of a class. (In fact, as we値l see in the next chapter, the effect of the private keyword is related to the scope of the unit containing the class.) The scope of an identifier (such as a variable, procedure, function, or a data type) is the portion of the code in which the identifier is accessible. The basic rule is that an identifier is meaningful only within its scope葉hat is, only within the block in which it is declared. You cannot use an identifier outside its scope. Here are some examples.
Pascal では、ユニットはカプセル化と可視性のキーになっていて、クラスのキーワードである private、public よりも、重要かも知れない。 ( 次の章でも説明するが、実のところ private キーワードは、クラスを保持しているユニットのスコープと関連がある。 ) 識別子 ( 変数、手続き、関数、データ型など ) のスコープは、その識別子にアクセス可能なコード群の内部に限られる。 基本的なルールを言えば、識別子はスコープ内部で、つまり、それが宣言されたブロック内部でのみ有効だ。 スコープを越えて、識別子を使うことはできない。 例を挙げてみよう。
Local variables: If you declare a variable within the block defining a routine or a method, you cannot use this variable outside that procedure. The scope of the identifier spans the whole procedure, including nested routines (unless an identifier with the same name in the nested routine hides the outer definition). The memory for this variable is allocated on the stack when the program executes the routine defining it. As soon as the routine terminates, the memory on the stack is automatically released.
ローカル変数:
ルーチンやメソッドを定義したブロック内部で変数を宣言すれば、この手続きを越えて、その変数を使うことはできない。 識別子のスコープは、ルーチンをネストして使っている場合も含め ( ただし、ネストしたルーチンの中で、同じ変数名を使えば、そのルーチンの中では外側の定義を無視する )、その手続き全体に及ぶ。 この変数のメモリ領域は、プログラムを実行してそのルーチンを使う際、メモリ・スタックに確保される。 そのルーチンが終了すると、スタック上のメモリ領域は、自動的に解放される。
Global hidden variables: If you declare an identifier in the implementation portion of a unit, you cannot use it outside the unit, but you can use it in any block and procedure defined within the unit. The memory for this variable is allocated as soon as the program starts and exists until it terminates. You can use the initialization section of the unit to provide a specific initial value.
隠れたグローバル変数:
ユニットの implmentation 部に識別子を宣言すれば、そのユニットの外では、その識別子を使うことはできない。 ユニットの中ならどこででも、ユニットの中の手続きの中ででも使うことができる。 変数のメモリ領域は、プログラムの始動と同時に確保され、プログラムが停止するまで存在し続ける。 ユニットの initialization 節を使えば、初期値を設定することもできる。
Global variables: If you declare an identifier in the interface portion of the unit, its scope extends to any other unit that uses the one declaring it. This variable uses memory and has the same lifetime as the previous group; the only difference is in its visibility.
グローバル変数:
ユニットの interface 部に識別子を宣言すれば、そのユニットを uses している、すべてのユニットから参照できるようにスコープが拡張される。 この変数のメモリ領域や、どのくらい生存し続けるかは、隠れたグローバル変数と同じだが、可視性には差がある。
Any declarations in the interface portion of a unit are accessible from any part of the program that includes the unit in its uses clause. Variables of form classes are declared in the same way, so that you can refer to a form (and its public fields, methods, properties, and components) from the code of any other form. Of course, it痴 poor programming practice to declare everything as global. Besides the obvious memory consumption problems, using global variables makes a program less easy to maintain and update. In short, you should use the smallest possible number of global variables.
ユニットの interface 部にある宣言は、そのユニットを uses しているユニットも含め、元のユニットにある、あらゆるプログラム・コードからアクセスできる。 フォームの変数についても同様で、別のフォームのコードから、そのフォーム ( それに、そのフォームの public 部、メソッド、プロパティ、それにコンポーネント ) を参照できる。 もちろん、なんでもグローバルとして宣言する、というのは、賢いプログラミングではない。 メモリを余計に食う、というだけでなく、グローバル変数を使うということは、更新や管理を難しくする。 手短に言えば、グローバル変数は、できるだけ少なくしろ、ということだ。
Units as Namespaces
名前空間 (XML) としてのユニット
The uses statement is the standard technique to access the scope of another unit. At that point you can access the definitions of the unit. But it might happen that two units you refer to declare the same identifier; that is, you might have two classes or two routines with the same name.
uses 文を使う、というのが、他のユニットにアクセスする、通常の手段だ。 こうすると、ユニットでの定義にアクセスできる。 しかし、ふたつのユニットが、同じ識別子、つまり同じ名前のクラスをふたつ、とか、同じ名前のルーチンを持っていることも考えられる。
In this case you can simply use the unit name to prefix the name of the type or routine defined in the unit. For example, you can refer to the ComputeTotal procedure defined in the given Totals unit as Totals.ComputeTotal. This should not be required very often, as you are strongly advised against using the same name for two different things in a program.
こういう時には、そのユニットで定義してあるルーチンの型名の頭に、ユニット名を付ければいい。 たとえば、Totals ユニットで定義してある ComputeTotal 手続きを参照するには、Totals.ComputeTotal とすればいい。 ただ、同じ名前を付ける、ということは、あまりやるべきではない。 ひとつのプログラムの中で、別のものを表すのに、同じ名前を使うことは、やめるべきだ。
However, if you look into the VCL library and the Windows files, you値l find that some Delphi functions have the same name as (but generally different parameters than) some Windows API functions available in Delphi itself. An example is the simple Beep procedure.
しかし、VCL ライブラリや Windows ファイルを覗いてみればいい。 Delphi で使っている Windows API 関数などで、いくつかの関数は同じ名前 ( ただ、パラメータは違っているのが普通だ ) になっているだろう。 Beep 手続きを使った例を見て欲しい。
If you create a new Delphi program, add a button, and write the following code:
新しいアプリをスタートさせ、ボタンををフォームに貼り付けて、下記のコードを書く。
procedure TForm1.Button1Click(Sender: TObject);
begin
Beep;
end;
then as soon as you press the button you値l hear a short sound. Now, move to the uses statement of the unit and change the code from this:
ボタンを押せば、Beep 音がする。 次に、ユニットの uses 部分が、こうなっているので、
uses
Windows, Messages, SysUtils, Classes, ...
to this very similar version (simply moving the SysUtils unit before the Windows unit):
こう変える ( SysUtils を Windows ユニットの前に持ってきただけだ )。
uses
SysUtils, Windows, Messages, Classes, ...
If you now try to recompile this code, you値l get a compiler error: "Not enough actual parameters." The problem is that the Windows unit defines another Beep function with two parameters. Stated more generally, what happens in the definitions of the first units you include in the uses statement might be hidden by corresponding definitions of later units. The safe solution is actually quite simple:
こうして、コンパイルしてみると、コンパイル・エラーになってしまう。 「パラメータが足りません」。 これは、Windows ユニットでは、パラメータがふたつ必要な Beep 関数が書かれているからだ。 一般的に言えば、uses 文で取り込んだユニットの内、最初のユニットの定義は、後のユニットで同様の定義がしてあれば、後のユニットで上書きされる、ということだ。 安全にやるなら、こうすればいい。
procedure TForm1.Button1Click(Sender: TObject);
begin
SysUtils.Beep;
end;
This code will compile regardless of the order of the units in the uses statements. There are few other name clashes in Delphi, simply because Delphi code is generally hosted by methods of classes. Having two methods with the same name in two different classes doesn稚 create any problem. The problems arise only with global routines.
こう書くと、uses 文のユニットの順序に関係なく動く。 このように、名前がぶつかることはいくつかあるが、これは、Delphi ではクラスのメソッドという考え方をしているからだ。 同じ名前のメソッドでも、それが別のクラスにあれば、なんら問題にならない。 問題が起こるのは、グローバルなスコープの時だけだ。
Units and Programs
ユニットとプログラム
A Delphi application consists of two kinds of source code files: one or more units and one program file. The units can be considered secondary files, which are referred to by the main part of the application, the program. In theory, this is true. In practice, the program file is usually an automatically generated file with a limited role. It simply needs to start up the program, running the main form. The code of the program file, or Delphi project file (DPR), can be edited either manually or by using the Project Manager and some of the Project Options related to the application object and the forms.
Delphi アプリでは、2種類のソースコード・ファイルを使う。 ユニットをひとつか複数、それにプログラム・ファイルだ。 ユニットは、二次ファイルとも言えるもので、アプリ ( 理屈で言うところのプログラム ) のメイン部分から参照される。 実際には、プログラム・ファイルは、役割としては限定的であり、自動的に生成される。 このファイルは、プログラムをスタートさせ、メイン・フォームを起動する。 プログラム・ファイルのコード、または Delphi プロジェクト・ファイル ( DPR ) は、手動でも編集できるし、Project Manager や、アプリケーション・オブジェクトとフォームに関連づけられている Project オプションで編集できる。
The structure of the program file is usually much simpler than the structure of the units. Here is the source code of a sample program file:
プログラム・ファイルの構造は、ユニットより遙かに単純だ。 サンプルを挙げてみると、
program Project1;
uses
Forms,
Unit1 in 繕nit1.PAS・{Form1DateForm};
begin
Application.Initialize;
Application.CreateForm (TForm1, Form1);
Application.Run;
end.
As you can see, there is simply a uses section and the main code of the application, enclosed by the begin and end keywords. The program痴 uses statement is particularly important, because it is used to manage the compilation and linking of the application.
これで分かるように、uses 節と、begin と end でくくられている、アプリのメイン・コードだけだ。 プログラムの uses 文は特に重要で、これによって、コンパイルとアプリのリンクを管理している。
Conclusion
結論
Units were the Pascal (actually Turbo Pascal) technique for module programming. Even if they were later followed b objects and classes, they still play a key role for encapsulation, for the definition of some sort of name spaces, and for the overall structure of Delphi programs. Also, units have influence on scope and global memory allocations.
ユニットは、モジュール・プログラミングを目的とした、Pascal ( 実際には Turbo Pascal ) の技術だった。 後にはオブジェクトとクラスになったが、ユニット技術は今も、その名前空間の定義や、Delphi プログラムの構造全体、そしてカプセル化に重要な役割を果たしている。 また、ユニットは、スコープと、グローバルなメモリ配置に影響を及ぼすものだ。
Next Chapter: Files in the Pascal Language
次章: Pascal 言語でのファイル
c Copyright Marco Cantu, Wintech Italia Srl 1995-2000