FreeBASIC マニュアルのトップに戻る

FreeBASIC TutIntroExtType

目次→教本→いっしょに学ぼうIntroduction to the Extended Type←オリジナル・サイト

拡張型への紹介 左にメニュー・フレームが表示されていない場合は、ここをクリックして下さい

←リンク元に戻る プログラム開発関連に戻る

序論

FreeBasic は、オブジェクト指向プログラミングを実装する方向に向かって、移行しています。
クラスは、まだ言語に追加されていませんが、Type 定義は、完全なクラスサポートに向かう第一歩として、いくつかのオブジェクト指向の構造物を含めるために、拡張されています。
この記事は、オブジェクト指向デザインの概念のいくつかを紹介して、拡張型構造物のいくつかについて説明します。


オブジェクト指向プログラミング

通常、OOP と短く呼ばれる オブジェクト指向プログラミングは、プログラマがオブジェクトと呼ばれるコード単位を組立てることを可能にする、方法論です。
オブジェクトは、プログラムの中で操られる必要がある、何かを表す、コードの単位です。
あなたは名詞としてオブジェクトを考えることができます:例えば、人、場所、もの。
オブジェクトは、例えば、基本図形のスプライトとか、ゲームの中に登場するタンクのように、より精巧な何か、かもしれません。
1セットの特性と機能を持っているどんな具体的な実体も、オブジェクトとして表すことができます。

オブジェクトは、オブジェクトが必要とするデータと、データに影響するメソッド(サブルーチンと関数)の、両方を含んでいます。
データとメソッドを、一つのエンティティ(単一体)に組分けることは、カプセル化、と呼ばれます。
あなたは、カプセル化で、複数のプログラムで再利用できるモジュラー・ユニットを作成できます。この、コード再利用の考えは、OOP の理論的枠組み作成の、主な動機でした。

カプセル化の別の有益な結果は、情報隠蔽です。
オブジェクトの中のデータは、データに求められていない変化が起こることができないように、外の世界から保護されます。
変数に直接アクセスする代わりに、オブジェクトには、外部プログラムが、データ・メンバーにアクセスして、変更するために使う、公開のインタフェースがあります。
インタフェースを使うことで、あなたは、オブジェクトがどう振る舞うかを制御できて、操作が多くのプログラムに対して一貫していることを、保証できます。

あなたは、インタフェースで、また、オブジェクトへのアクセス方法を変えずに、コード内の変更を行うことができます。
これは、既存の公開のメソッドを変えることです。あなたが、公開したインタフェースを変えない限り、オブジェクトを当てにするどんな既存のコードも変えずに、あなたはオブジェクトを改良できます。
プログラムで、改善したメソッドが必要なとき、あなたは互換性を維持するために、古いメソッドを残すことができます。そして、機能を向上させたと新しいメソッドを、加えるだけです。
新しいプログラムは新しいメソッドを使用できますし、古いプログラムは、まだ古いメソッドを使用できます。

公開のインタフェースを使う別の利点は、他のプログラマが、あなたのオブジェクトを、そのオブジェクト内の細部を心配せずに利用できることです。
公開されたインタフェースが、安定していて、説明が行き届いていれば、だれでもあなたのオブジェクトを利用できるでしょう。初心者でさえも。


公開された契約

前述のとおり、OOP は、プログラマの間で、コードを再利用できるようにするために、設計されました。
コード再利用が役立つように、公開されたインタフェースは、安定した状態を保たなければなりません。
すなわち、いったんオブジェクトが発行されて、プログラムで使われると、公開されたインタフェースは変更されないので、オブジェクトを使うプログラムは、正しく働き続けます。
オブジェクトの作者としてのあなたと、あなたのオブジェクトのエンドユーザとの間に、あなたは、オブジェクトに加える必要がある変更にかかわらず、公開したインタフェースを維持する、という、暗黙の契約があります。
作者とユーザの間の、この暗黙の契約は、OOP の理論的枠組みの主な強さであり、OOP がこのような強力なプログラミング方法論になった、主な理由です。


オブジェクトの特性

既に言及したように、オブジェクトは、データとメソッドの両方を含んでいます。
データは、オブジェクトの特性を説明します。メソッドは、オブジェクトができることを説明します。
簡単な、実際には役に立たない例で、この概念を説明します。

画面に長方形を描くオブジェクトを作成したい、と仮定してください。
長方形は、オブジェクトのデータ・メンバーの中に含まれている、数個の特性を持つことができます。
長方形は、画面の上に起点を持っています。通常、左上の隅です。x と y データ・メンバーは、起点からの距離です。
長方形には、幅と高さがあるので、オブジェクトは、幅と高さのデータ・メンバーを持つでしょう。
長方形は、外枠だけか、塗りつぶした状態があるので、塗りつぶしフラグのデータ・メンバーを、オブジェクトに加えることができます。
もちろん、長方形を描くとき、あなたは特定の色で描きたいことがあるでしょう。したがって、オブジェクトは、カラー・データ・メンバーが必要です。オブジェクトが、もう少しフレキシブルであれば、あなたは外枠のためのカラー・メンバーと、塗りつぶしのための別のカラー・メンバーを加えることができます。
もちろん、実際に画面に長方形を描くためのメソッドが必要なので、あなたは描画ルーチンをオブジェクト定義に加えることができます。

それで、私たちの長方形オブジェクトには、下の仮の特性とメソッドがあります:

このリストは、オブジェクト定義と呼ばれます。
FreeBasic では、拡張 Type 定義を使ってオブジェクトを定義します。
拡張 Type は、標準 Type と同様です。拡張 Type は、いくつかの加えられた言語構築とともに、OOP の特徴の部分集合を実装します。


長方形の型定義

下の短いコードは、部分的な長方形定義です:

Type myRect
  Private:
    X_ As Integer
    Y_ As Integer
    Width_ As Integer
    Height_ As Integer
    Filled_ As Integer
    Otlncolor_ As Integer
    Fillcolor_ As Integer
    Public:
    Declare Sub DrawRect ()
End Type


お分かりのように、拡張 Type は、Private: と Public: キーワードと sub 宣言を除くと、標準 Type のように見えます。
Private: キーワードは、コンパイラに、これに続くデータ・メンバーは、型に対して、非公開である、と伝えます。これは、型の外からアクセスできません。
非公開の状態は、新しい限定子に遭遇するまで、すべてのオブジェクトのメンバーに適用されます。この場合、新しい限定子は、Sub 宣言の直前の Public: 限定子です。
すべてのデータ・メンバーは、外の世界に対して隠されていて、Type の範囲の外から変えることができません。情報隠蔽と呼ばれるプロセスです。
非公開変数名の後ろの下線文字は、非公開変数を定義する、一般的な方法です。

情報隠蔽は、オブジェクトの完全性を維持する方法です。
あなたは、外のプロセスを、データメンバーに、決して直接アクセスさせてはいけません。
すべてのデータは、Property メンバーを経由してアクセスさせるようにして、オブジェクトに渡されているものを制御できるようにします。
オブジェクトのデータを厳重に管理することで、プログラマがオブジェクトを使うときに発生する可能性がある、多くの誤りを、予防できます。

Type myRect
  Private:
    X_ As Integer
    Y_ As Integer
    Width_ As Integer
    Height_ As Integer
    Filled_ As Integer
    Otlncolor_ As Integer
    Fillcolor_ As Integer
    Public:
    Declare Sub DrawRect ()
    Declare Property X (ByVal xx_ As Integer)
    Declare Property X() As Integer
    Declare Property Y (ByVal yy_ As Integer)
    Declare Property Y() As Integer
    Declare Property Width (ByVal w_ As Integer)
    Declare Property Width() As Integer
    Declare Property Height (ByVal h_ As Integer)
    Declare Property Height() As Integer
    Declare Property Filled (ByVal f_ As Integer)
    Declare Property Filled() As Integer
    Declare Property Otlncolor (ByVal oc_ As Integer)
    Declare Property Otlncolor() As Integer
    Declare Property FillColor (ByVal fc_ As Integer)
    Declare Property FillColor() As Integer
End Type


Public: 限定子に続く、Declare 命令文は、オブジェクトへの公開インタフェースを包含します。
型の変数は、Private: キーワードと共に定義されているので、変数にアクセスする唯一の方法は、オブジェクトの完全性を維持している、Property メンバーを通してだけです。
それぞれの Property メンバーの中で、コードを定義するので、あなたは、オブジェクトに入れられているものを、完全にコントロールできます。
この一般的な例は、特性のメンバーに、範囲検査コードを入れることです。オブジェクトが無効データを含まないようにするためです。

この例では、変数は、読み書き、できます。
コンパイラは、メソッドの型で、読み Property と、書き Property を見分けます。
サブルーチンでフォーマットされた Property は、非公開変数に保存された値を渡しているので、書き特性です。
関数でフォーマットされた Property は、非公開変数が呼び出し先に返されるので、読み特性です。
あなたは、まさしく関数でフォーマットされた Property を加えることによって、書き込み禁止 Property を作成できます。あるいは、ただサブルーチンでフォーマットされた Property を加えることで、書き込み Property を作成できます。


正常に動作するオブジェクトを作成する

定義は、ここで完全に見えますが、問題があります。
変数のいくつか、あるいは、すべてが初期化されないと、何が起こるでしょうか?
オブジェクトは、正しく実行しないで、潜在的に実行時エラーを引き起こしません。
一つまたは複数の変数が初期化されないときのために、オブジェクト変数のための、デフォルト値のセットを持っているほうがよいでしょう。
Constructor(構築子) を使って、オブジェクトを作成するときに、初期化できます。

Constructor(構築子) は、オブジェクトが、Dim(または、New)命令文を使って作られるときに呼ばれる、サブルーチンです。
構築子は、オブジェクトを、デフォルト値か、または、あなたが 構築子 に渡す値で、初期化することの役に立ちます。
これらを織り込んだ型定義は、下のようになるでしょう:

Type myRect
  Private:
    X_ As Integer
    Y_ As Integer
    Width_ As Integer
    Height_ As Integer
    Filled_ As Integer
    Otlncolor_ As Integer
    Fillcolor_ As Integer
    Public:
    Declare Sub DrawRect ()
    Declare Property X (ByVal xx_ As Integer)
    Declare Property X() As Integer
    Declare Property Y (ByVal yy_ As Integer)
    Declare Property Y() As Integer
    Declare Property Width (ByVal w_ As Integer)
    Declare Property Width() As Integer
    Declare Property Height (ByVal h_ As Integer)
    Declare Property Height() As Integer
    Declare Property Filled (ByVal f_ As Integer)
    Declare Property Filled() As Integer
    Declare Property Otlncolor (ByVal oc_ As Integer)
    Declare Property Otlncolor() As Integer
    Declare Property FillColor (ByVal fc_ As Integer)
    Declare Property FillColor() As Integer
    Declare Constructor ()
    Declare Constructor(xx_ As Integer, yy_ As Integer, w_ As Integer, _
                        h_ As Integer, f_ As Integer, oc_ As Integer, _
                        fc_ As Integer)
End Type


あなたは、定義で、私たちが 2 つのConstructor(構築子) (一組のパラメータを持つもの、持っていないもの) を設定しているのに、気がつくでしょう。
これは、多重定義と呼ばれて、Constructor と共に使用されるだけではなく、他のサブルーチンや関数と共にも使用できます。
多重定義は、ただ一つのメソッド呼び出しで、異なったパラメータの型を扱う必要がある状況で、役に立ちます。
コンパイラは、メソッドに渡されるパラメータにもとづいて、どのメソッドを呼ぶか、を決定します。
あなたは、好きなだけ多く、メソッドを多重定義することができます。各メソッドのためのパラメタの数と型が、ユニークである限り。

この場合、Constructor が、何のパラメタ値も渡されないと、Constructor は、変数を、デフォルト値のセットで、初期化します。
Constructor が、パラメタ付きで呼ばれると、Constructor は、オブジェクトの変数を初期化するのに、渡された値を使います。

また、オブジェクトが破壊されるとき呼ばれる、Destructor メソッドがあります。
Destructor を使って、オブジェクトがメモリから解放される前に、行わなければならない全てのクリーンアップ・タスクを、実行できます。
オブジェクトが、何かポインタ参照を作成していたり、または何かファイルを開いていても、Destructor で、これらの参照を、消去できます。
Rectangle オブジェクトは、どんな外部の参照も作成しないので、Destructor は、必要ありません。


オブジェクト・メソッドを記入する

型定義は、オブジェクト型のためのテンプレートであり、メモリでオブジェクトをセットアップする方法を、コンパイラに伝えます。
しかし、オブジェクトを実際に使うために、あなたは、実際の呼び出しメソッドを、作成する必要があります。
下のリストを参照下さい。

Type myRect
  Private:
    X_ As Integer
    Y_ As Integer
    Width_ As Integer
    Height_ As Integer
    Filled_ As Integer
    Otlncolor_ As Integer
    Fillcolor_ As Integer
    Public:
    Declare Sub DrawRect ()
    Declare Property X (ByVal xx_ As Integer)
    Declare Property X() As Integer
    Declare Property Y (ByVal yy_ As Integer)
    Declare Property Y() As Integer
    Declare Property Width (ByVal w_ As Integer)
    Declare Property Width() As Integer
    Declare Property Height (ByVal h_ As Integer)
    Declare Property Height() As Integer
    Declare Property Filled (ByVal f_ As Integer)
    Declare Property Filled() As Integer
    Declare Property Otlncolor (ByVal oc_ As Integer)
    Declare Property Otlncolor() As Integer
    Declare Property FillColor (ByVal fc_ As Integer)
    Declare Property FillColor() As Integer
    Declare Constructor ()
    Declare Constructor(xx_ As Integer, yy_ As Integer, w_ As Integer, _
                        h_ As Integer, f_ As Integer, oc_ As Integer, _
                        fc_ As Integer)
End Type

Sub myRect.DrawRect ()
    Line (This.x_, This.y_)-(This.x_ + Width - 1, This.y_ + This.height_ - 1), This.Otlncolor_, B
    If This.Filled_ <> 0 Then
        Paint (This.x_ + 1, This.y_ + 1), This.Fillcolor_, This.Otlncolor_
    End If   
End Sub

Property myRect.x (ByVal xx_ As Integer)
    This.X_ = xx_
End Property

Property myRect.x() As Integer
    Return This.X_
End Property

Property myRect.y (ByVal yy_ As Integer)
    This.Y_ = yy_
End Property

Property myRect.y() As Integer
    Return This.y_
End Property

Property myRect.Width (ByVal w_ As Integer)
    This.Width_ = w_
End Property

Property myRect.Width() As Integer
    Return This.Width_
End Property

Property myRect.Height (ByVal h_ As Integer)
    This.Height_ = h_
End Property

Property myRect.Height() As Integer
    Return This.Height_
End Property

Property myRect.Filled (ByVal f_ As Integer)
    This.Filled_ = f_
End Property

Property myRect.Filled() As Integer
    Return This.Filled_
End Property

Property myRect.Otlncolor (ByVal oc_ As Integer)
    This.Otlncolor_ = oc_
End Property

Property myRect.Otlncolor() As Integer
    Return This.Otlncolor_
End Property

Property myRect.FillColor (ByVal fc_ As Integer)
    This.Fillcolor_ = fc_
End Property

Property myRect.FillColor() As Integer
    Return This.Fillcolor_
End Property

Constructor myRect
    This.X_ = 0
    This.Y_ = 0
    This.Width_ = 10
    This.Height_ = 10
    This.Filled_ = 0 
    This.Otlncolor_ = 15
    This.Fillcolor_ = 7
End Constructor

Constructor MyRect (xx_ As Integer, yy_ As Integer, w_ As Integer, _
                        h_ As Integer, f_ As Integer, oc_ As Integer, _
                        fc_ As Integer)
    This.X_ = xx_
    This.Y_ = yy_
    This.Width_ = w_
    This.Height_ = h_
    This.Filled_ = f_ 
    This.Otlncolor_ = oc_
    This.Fillcolor_ = fc_
End Constructor


メソッドとプロパティは、Sub/Function/Property TypeName.methodname 構文を使って定義されます。
これは、メソッドを、適切な型定義と一致させる方法を、コンパイラーに指示します。
コンストラクタは、同じ理由で、型名で定義されます。
this 識別子は、定義された型を参照するメソッドに渡される、隠しパラメータです。
this 識別子を使って、型構成にアクセスすることを指定します。

あなたのオブジェクトを使う

オブジェクトは、今、完成しました。下にリストアップされているプログラムで、使えます。

Type myRect
  Private:
    X_ As Integer
    Y_ As Integer
    Width_ As Integer
    Height_ As Integer
    Filled_ As Integer
    Otlncolor_ As Integer
    Fillcolor_ As Integer
    Public:
    Declare Sub DrawRect ()
    Declare Property X (ByVal xx_ As Integer)
    Declare Property X() As Integer
    Declare Property Y (ByVal yy_ As Integer)
    Declare Property Y() As Integer
    Declare Property Width (ByVal w_ As Integer)
    Declare Property Width() As Integer
    Declare Property Height (ByVal h_ As Integer)
    Declare Property Height() As Integer
    Declare Property Filled (ByVal f_ As Integer)
    Declare Property Filled() As Integer
    Declare Property Otlncolor (ByVal oc_ As Integer)
    Declare Property Otlncolor() As Integer
    Declare Property FillColor (ByVal fc_ As Integer)
    Declare Property FillColor() As Integer
    Declare Constructor ()
    Declare Constructor(xx_ As Integer, yy_ As Integer, w_ As Integer, _
                        h_ As Integer, f_ As Integer, oc_ As Integer, _
                        fc_ As Integer)
End Type

Sub myRect.DrawRect ()
    Line (This.x_, This.y_)-(This.x_ + This.Width_ - 1, This.y_ + This.height_ - 1), This.Otlncolor_, B
    If This.Filled_ <> 0 Then
        Paint (This.x_ + 1, This.y_ + 1), This.Fillcolor_, This.Otlncolor_
    End If   
End Sub

Property myRect.x (ByVal xx_ As Integer)
    This.X_ = xx_
End Property

Property myRect.x() As Integer
    Return This.X_
End Property

Property myRect.y (ByVal yy_ As Integer)
    This.Y_ = yy_
End Property

Property myRect.y() As Integer
    Return This.y_
End Property

Property myRect.Width (ByVal w_ As Integer)
    This.Width_ = w_
End Property

Property myRect.Width() As Integer
    Return This.Width_
End Property

Property myRect.Height (ByVal h_ As Integer)
    This.Height_ = h_
End Property

Property myRect.Height() As Integer
    Return This.Height_
End Property

Property myRect.Filled (ByVal f_ As Integer)
    This.Filled_ = f_
End Property

Property myRect.Filled() As Integer
    Return This.Filled_
End Property

Property myRect.Otlncolor (ByVal oc_ As Integer)
    This.Otlncolor_ = oc_
End Property

Property myRect.Otlncolor() As Integer
    Return This.Otlncolor_
End Property

Property myRect.FillColor (ByVal fc_ As Integer)
    This.Fillcolor_ = fc_
End Property

Property myRect.FillColor() As Integer
    Return This.Fillcolor_
End Property

Constructor myRect
    This.X_ = 0
    This.Y_ = 0
    This.Width_ = 10
    This.Height_ = 10
    This.Filled_ = 0 
    This.Otlncolor_ = 15
    This.Fillcolor_ = 7
End Constructor

Constructor MyRect (xx_ As Integer, yy_ As Integer, w_ As Integer, _
                        h_ As Integer, f_ As Integer, oc_ As Integer, _
                        fc_ As Integer)
    This.X_ = xx_
    This.Y_ = yy_
    This.Width_ = w_
    This.Height_ = h_
    This.Filled_ = f_ 
    This.Otlncolor_ = oc_
    This.Fillcolor_ = fc_
End Constructor

'描画画面を作成します
Screen 18

'デフォルト 構築子 を使って、オブジェクトを作成します
Dim aRect As myRect
'明示的に構築子値を設定して、オブジェクトを作成します
Dim bRect As myRect = myRect (200, 200, 200, 100, 1, 15, 9)

'長方形を画面に描きます
aRect.DrawRect
bRect.DrawRect

'aRect の特性を更新します
aRect.X = 90
aRect.Y = 20
aRect.Filled = 1
aRect.FillColor = 15

'新しい長方形を描きます
aRect.DrawRect
Sleep
End


デフォルト Constructor を使ってオブジェクトを初期化するには、ちょうど標準の型でするように、単に、拡張の Type を Dim するだけです。
Constructor が、ただ一つの値を取るだけなら、Dim var as Typename = value の構文を、使えます。
オブジェクトを、値のセットで初期化するには、型を Dim して、次に、= typename(par1m parm1 ...) 構文を使います。
あなたは、オブジェクトのメンバーにアクセスすることが、まるで、標準の型のメンバーにアクセスするようであることが、分かるでしょう。

cha0s さん、FreeBasicフォーラムでの、Properties に関連する情報を、ありがとうございました。

いっしょに学ぼう に戻る
←リンク元に戻る プログラム開発関連に戻る

ページ歴史:2018-02-10 13:16:25
日本語翻訳:WATANABE Makoto、原文著作者:WikiRick(Rick Clark aka rdc)

ホームページのトップに戻る

表示-非営利-継承