こんにちは、みなさん。
この講義ではクラスメソッドに注目します。
前に見た通り
クラスメソッドは 他のメソッド同様の通常のメソッドです。
一般に、新しいインスタンスを作るために 使いますが
他のことにも使われます。
クラスメソッドの使い方について 2つの例を見ましょう。
仮に、コンピュータプログラムで
これらの行をパースしたいとします。
これらの行は構造を作っています。
感嘆符（!）で始まる行は
タイトルとして読み込まれます。
ダッシュ（-）で始まる行は リストのアイテムです。
1つより多くのダッシュで始まる行は
リストのサブアイテムです。
他の場合は、段落です。
これらを入力とするプログラムで
DocumentItem のサブクラスの
インスタンスを作ります。
また、このプログラムの設計として
DocumentItem の各サブクラスが
行をパースする責任を持っていて
与えられた行について canParse: を決めることにします。
ここの canParse: メソッドでは 1行のテキストを渡します。
その行が感嘆符で始まっていたら
canParse: メソッドは true を返します。
その行は、SectionTitle クラス に属します。
LiteItem クラスでは
canParse: メソッドはダッシュで始まる行に true を返します。
そして、この canParse: は常に true を返します。
考え方としては、クラスを1つ1つ見ていって
与えられた行をパースできるクラスを見つけ次第
そのクラスを使って、その行をパースした 新しいインスタンスを作る、ということです。
それが canParse: メソッドのゴールです。
newFromLine: メソッドは 1 行のテキストを引数として取って
その行を表すインスタンスを返します。
newFromLine: メッセージが SectionTitle クラスに送られて
感嘆符で始まる一連の文字が渡されたら
newFromLine: メソッドは SectionTitle クラスのインスタンスを返します。
こんな風に動くようにします。
Parser クラスがすることは
DocumentItem のサブクラスの中から
与えられた行を担当するものを探します。
Parser は documentClasses という メソッドを持っています。
そのメソッドは DocumentItem の
サブクラスのリストを返します。
これらのクラスを含む コレクションを返します。
DocumentItem に allSubclasses メッセージを送ります。
allSubclasses メソッドは Pharo システムに 既に存在しています。
与えられたクラスの サブクラスのリストを返します。
このメッセージの結果
SectionTitle と ListItem と Text を含むコレクションが得られます。
このコレクションを優先順位によって 並べておきます。
そうすることで、Text クラスが最後に なるようにします。
というのも、Text クラスの canParse: メソッドは 常に true を返すからです。
Text クラスはどんな行でも パースできてしまいます。
他のクラスを試したあとで、 Text クラスを試します。
そのために優先順位という概念を使います。
見ての通り、多くのメソッドに 下線が引かれています。
メソッドに下線を引かれていると
それはクラスメソッドだということを 示しています。
これらのメソッドを実行するためには メッセージをクラスに送らなければなりません。
canParse: メソッドを SectionTitle クラスに送って
SectionTitle クラスが与えられた行を パースできるかどうか見なければなりません。
Parser クラスの parse: メソッドは 行を引数として受け取ります。
DocumentItem の全てのサブクラスから その行をパースできるクラスを探します。
見つかれば そのクラスのインスタンスを作ります。
detect: をコレクションに送ることで
そのコレクションの要素の中から 述語を満たすものを得ます。
さて、クラスメソッドを使う もう 1 つの例を見てみましょう。
コマンドラインの引数をどのように扱っているか 見てみましょう。
ここでは 引数を受け取って
処理を変える引数を見つける プログラムを見ていきます。
最初の引数はアクションが実行されることを示しています。
プログラムの設計として アクションの種類ごとに 1つのクラスを持つようにします。
eval アクションは1つのクラスで表現されます。
EvaluateCommandLineHandler です。
eval が引数として現れた時に どんなアクションが実行されるでしょうか？
実行するのは…
この一連の文字列が Pharo のコードとして解釈されて
その表現式の結果が返されます。
3628800 が 10 factorial の結果です。
これは
CommandLineHandler クラス を使って実装されています。
EvaluateCommandLineHandler は
eval の処理を担当するサブクラスです。
eval がコマンドラインの 最初の引数として送られたら
このクラスが処理しなければなりません。
isReponsibleFor: メソッドが true を返すのは
サブクラスが
このコマンドラインを処理する能力が ある場合です。
その背後には
前の例で見たのと同じメカニズムがあります。
もう1度言いますが、クラスメソッド そしてクラスへのメッセージ送信は
インスタンスを作ること以外の仕事にも 使われます。
この講義ではクラスメソッドの 2つの利用例を見ました。
クラスメソッドは多くの場合 新しいインスタンスを作るために使われます。
しかし、他の使い方もあります。