このビデオでは、Pharo の講義では あまりカバーされないことを説明します。
可変長のオブジェクトを 定義する方法です。
お気付きでしょうが、我々はもう既に サイズが異なるオブジェクトを使っています。
この表現式で配列を作ります。
10 個の要素を持っていて いずれも nil がセットされています。
同じような表現式で 5 個の要素を持つ
配列を作ります。
Array クラスは色々なサイズの インスタンスを作ることがわかります。
しかし、これまで、どうやっているのか 説明をしてきませんでした。
そこで
色々なサイズのインスタンスを持つ クラスを定義する方法と
インスタンスを生成する方法と
可変なサイズにアクセスする方法を お見せします。
では 1 つ目です。
とても簡単です。
定義する時に subclass: の代わりに variableSubclass: を使います。
Array クラスの定義をコピーします。
大事なのは、クラスを生成するために
variableSubclass:instanceVariableNames: ... を使うことです。
一方、通常は Point クラスや
Counter クラスや Dice クラスのように
subclass: を使います。
この定義を使うことで インスタンスのサイズが可変になります。
この例では StrangePoint を定義していますが
Point として 2 つのインスタンス変数 x と y
さらに可変長な領域を持ちます。
すると、こんな感じのオブジェクトができます。 インスタンスごとに、x の値と
y の値と 可変長領域があります。
別のインスタンスにも
x と y があって、 x はそれぞれ 10 と 20 で
y は例えば 100 と 200 で
それぞれオブジェクトを格納できる 可変長領域を持っています。
色々なサイズのインスタンスを 持つクラスのインスタンスは
x や y のような名前のある変数の後に インデックス領域があります。
インデックス領域には名前はついておらず 1 つのクラスに 1 つしか持つことができません。
実装上の問題を避けるために そうなっています。
これで、異なるサイズのインスタンスを持つ クラスを定義する方法が
わかりましたね。
ではインスタンスを生成する方法と
可変長にアクセスする方法に 進みましょう。
インスタンスを生成するためには
new: メッセージを使います。 コロンが付いていることに注意してください。
コレクションの講義でやりましたね。
ここでは異なるサイズのオブジェクトを 生成したいわけですが
オブジェクトのサイズは max で指定されます。
こうして 4 要素の配列という オブジェクトを生成します。
こんな風に 4 つの要素を示します。
この可変サイズにアクセスするには
at: メッセージや at:put: メッセージを 使います。配列で見た通りです。
可変サイズのオブジェクトはどれでも この方法で使うことができます。
つまり、ここで at: 2 とすると 'lulu' が入れられます。
1 つ目の値にアクセスすると 当然ですが nil が返ってきます。
2 つ目の値を見ると 'lulu' が得られます。
実際、at:put: や 'lulu' のような 配列の使い方は
可変サイズのオブジェクトにも 当てはまります。
この API プロトコルは配列にも
可変サイズのあらゆるオブジェクトにも 使うことができます。
ここではあまり多くは説明しませんが
Array クラスを定義する方法を 他のオブジェクトにも展開できます。
プロトコルを知っているからです。
Pharo では 色々な形態の
オブジェクトやクラスがあります。
名前がついたインスタンス変数しか 持たないクラスがあります。
count を持つ Counter クラスや 面の数を持つ Dice クラスのようなものです。
また、可変、あるいはインデックス領域 のみを持つクラスもあります。
配列などです。
そしてまた、その両方を持ち合わせた クラスもあります。
しかし、制約条件もあります。 思った以上に微妙なものです。
これでクラスの可変性を 決めることができます。
ここではそれぞれの目的を示すに留めます。
これらの可変領域は
オブジェクトポインタや バイトやワードを格納します。
それらは外部の世界との インターフェイスに使われます。
サイズを指定して
オブジェクトへのポインタを 特殊な形式で格納します。
これは上級向けの機能ですが お見せしておきたかったのです。
普段は subclass: しか 使う必要はないでしょう。
時々、variableSubclass: を 使うことになるでしょう。
Bitmap はスクリーンを表す
オブジェクトですが
ワードを格納する可変長領域があります。
そういうものがある ということを知っておいてください。
Pharo はリフレクティブなシステムなので
質問は Pharo に訊けばよいのです。
これらのメソッドを使って Pharo に訊くことができます。
クラスのサイズが固定か可変かや
ポインタを格納するのか、バイトなのか などです。
クラスの種類について質問するための API があります。
この表も、システムに質問して 作成しました。
制約があります。
subclass: で定義されたクラスの
サブクラスはどの種類でもかまいません。
x や y を持つ Point があるとして
加えて z を持つサブクラスを定義することも
可変領域を追加したサブクラスを 定義することもできます。
しかし、可変領域を持つクラスの サブクラスを作る場合には
その可変領域のクラスの 可変領域しか使うことはできません。
破ろうとすると システムが互換性がないと言います。
可変領域は 1 つしか持てないのです。
いずれにせよ、システムは それは不可能だと言います。
理解しておくべきことは
可変長のインスタンスを持つクラスを
定義する方法と
new: でインスタンスを生成する方法と
可変領域へアクセスする方法で これは配列でのアクセスと同様です。