卒研で汎用的な物を作っていく中で、本来の処理とは別に、この対象の時は、特別な処理をしたいということが出てくる。しかし、この処理を if ( … ) で管理するとプログラムのコードが煩雑となることも多い。この時のターゲットに応じた特別な処理は、Hook(フック)と呼ぶ。
「Hook(フック)」は、プログラミングにおいて、既存のプログラムの特定の処理の途中に、別のカスタムな処理を差し込む(「引っ掛ける」)ための仕組みを指します。まるでプログラムの実行の流れに「釣り針」を引っ掛けて、自分のコードを実行するようなイメージです。(Geminiより)
struct Target{ int id ; // 識別用のID : } ; void action_Target( Target* t ) { if ( t.id == T_FOO ) { // 特別前処理_FOO } else if ( t.id == T_BAR ) { // 特別前処理_BAR } // 通常処理 : if ( t.id == T_FOO ) { // 特別後処理_FOO } else if ( t.id == T_BAR ) { // 特別後処理_BAR } }
このようなプログラムでは、action_Target() が、どんどん肥大化して、メンテナンスが面倒になる。
C言語であれば、関数ポインタを用いて、以下のような実装とするかもしれない。
struct Target { int id ; void (*action_pre_hook)( Target* t ) ; void (*action_post_hook)( Target* t ) ; : } ; void action_foo_pre_hook( Target* t ) { // 特別前処理_FOO } void action_foo_post_hook( Target* t ) { // 特別後処理_FOO } struct Target target_FOO = { T_FOO , action_foo_pre_hook , // 特別前処理が必要なら関数を登録しておく action_foo_post_hook , : } ; void action_Target( Target* t ) { if ( t->action_pre_hook != NULL ) // 特別前処理を呼び出す t->action_pre_hook( t ) ; // 通常処理 if ( t->action_post_hook != NULL ) // 特別前処理を呼び出す t->action_post_hook( t ) ; }
オブジェクト指向を使える言語であれば、仮想関数などを用いて実装するのが普通だろう。
class Target { virtual void action_pre_hook() = 0 ; // 仮想関数 virtual void action_post_hook() = 0 ; void action() { action_pre_hook() ; // 通常処理 action_post_hook() ; } } ; class Target_FOO : public Target { virtual void action_pre_hook() { // 特別前処理 } virtual void action_post_hook() { // 特別後処理 } } ;
JavaScript などの言語であれば、無名関数やラムダ式などでフックを登録するのが普通であろう。
const target_foo = { pre_hook: function( target t ) { // 特別前処理 } , post_hook: function( target t ) { // 特別後処理 } , : } ; function action( target t ) { t.pre_hook( t ) ; // 通常処理 t.post_hook( t ) ; }