7.6.6.2. Standard Method-Combination
method-combinationのstandardは、standard-generic-functionクラスによって提供されます。 これはmethod-combinationのタイプが指定されなかった場合か、 あるいは組み込みのmethod-combinationタイプであるstandardが指定された場合に使われます。
プライマリメソッドは有効なメソッドのメインとなる動作として定義されます。 補助メソッドは3つあるうちの1つの方法を用いて動作を変更します。 プライマリメソッドは修飾子を持ちません。
補助メソッドは、修飾子:before, :after, そして:aroundのメソッドです。 method-combinationのstandardは、メソッドに対して2つ以上の修飾子を許容しません。 もしメソッド定義で複数の修飾子をもつメソッドを定義した場合は、エラーが発せられます。
beforeメソッドは、ただひとつの修飾子として:beforeキーワードを持ちます。 beforeメソッドは、プライマリメソッドの前に実行されるコードを定義します。
afterメソッドは、ただひとつの修飾子として:afterキーワードを持ちます。 afterメソッドは、プライマリメソッドの後に実行されるコードを定義します。
aroundメソッドは、ただひとつの修飾子として:aroundキーワードを持ちます。 aroundメソッドは、他の適用可能なメソッドの代わりとして実行されますが、 いくつかのシャドウされたメソッドを(call-next-method経由で)呼び出すコードを、 明に含むことができます。
method-combinationのstandardの意味を次に示します。
もしaroundメソッドが存在する場合は、最も特定的なaroundメソッドが呼ばれます。 これはジェネリック関数に対して1つか複数の返却値を提供します。
aroundメソッドのコード内では、次のメソッドを呼ぶためのcall-next-methodが使用できます。 次のメソッドから戻ったとき、aroundメソッドは返却された値に基づいて、 さらにコードを実行することができます。 もしcall-next-methodを使用したときに呼び出せる適用可能なメソッドが存在しなかった場合は、 ジェネリック関数no-next-methodが呼び出されます。 関数next-method-pは、次のメソッドが存在するかどうかを決定するために使われます。
もしaroundメソッドがcall-next-methodを実行したとき、 次の特定的なaroundメソッドが適用可能であれば呼び出されます。 もしaroundメソッドが存在しないか、 あるいは最も特定的ではないaroundメソッドによってcall-next-methodが呼び出された場合は、 次に示すものとして他のメソッドが呼び出されます。
全てのbeforeメソッドがmost-specific-firstの順番で呼ばれます。 これらの返却値は無視されます。 もしbeforeメソッド内でcall-next-methodが使用された場合は、エラーが発せられます。
最も特定的なプライマリメソッドが呼び出されます。 プライマリメソッドのコード内では、 次の特定的なプライマリメソッドを呼び出すためのcall-next-methodが使用できます。 メソッドから戻ったとき、以前のプライマリメソッドは返却された値に基づいて、 さらにコードを実行することができます。 もしcall-next-methodを使用したときに、呼び出せる適用可能なメソッドが存在しなかった場合は、 ジェネリック関数no-next-methodが呼び出されます。 関数next-method-pは、次のメソッドが存在するかどうかを決定するために使われます。 もしcall-next-methodが使われなかった場合は、最も特定的なプライマリメソッドだけが呼び出されます。
全てのafterメソッドがmost-specific-lastの順番で呼ばれます。 これらの返却値は無視されます。 もしafterメソッド内でcall-next-methodが使用された場合は、エラーが発せられます。
もしaroundメソッドが呼び出されなかった場合は、 最も特定的なプライマリメソッドが、 1つか複数の値をジェネリック関数の返却値として返却します。 最も特定的ではないaroundメソッドから call-next-methodの呼び出しによって返却される1つか複数の返却値は、 最も特定的なプライマリメソッドの返却値となります。
method-combinationのstandardでは、適用可能なメソッドが存在しても、 適用可能なプライマリメソッドが存在しなかった場合はエラーが発せられます。
beforeメソッドはmost-specific-first順にて実行され、 afterメソッドはleast-specific-first順に実行されます。 この設計の違いの根拠を、例として次のように示します。 クラスC1がスーパークラスであるC2の動作を、 beforeメソッドとafterメソッドに追加することで変更することを考えます。 クラスC2の振る舞いがC2のメソッドとして直接定義するか、 あるいはスーパクラスを継承によるものかに関わらず、 クラスC1のインスタンスによって呼び出されるメソッドの相対的な順番には影響しません。 クラスC1のbeforeメソッドは、クラスC2の全てのメソッドの前に実行されます。 クラスC1のafterメソッドは、クラスC2の全てのメソッドの後に実行されます。
対称的に、全てのaroundメソッドが実行されるのは、他のメソッドが実行される前です。 このように最も遠いaroundメソッドは、最も特定的なプライマリメソッドの前に実行されます。
もしプライマリメソッドのみが宣言されており、 さらにcall-next-methodが使用されなかった場合は、 最も特定的なメソッドのみが実行されます。 つまり最も特定的なメソッドが他の一般的なメソッドをシャドウしたということです。