卒研で汎用的な物を作っていく中で、本来の処理とは別に、この対象の時は、特別な処理をしたいということが出てくる。しかし、この処理を 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 ) ;
}