コンピュータプログラミングにおいて、ジェネリック関数とは、ポリモーフィズムのために定義された関数のことである。
静的型付け言語( C++やJavaなど)では、ジェネリック関数という用語は、コンパイル時多態性(静的ディスパッチ)のメカニズム、特にパラメトリック多態性を指します。これらは型パラメータで定義された関数であり、コンパイル時の型情報を用いて解決されることを意図しています。コンパイラはこれらの型を使用して適切なバージョンをインスタンス化し、関数オーバーロードを適切に解決します。
Common Lisp Object System (CLOS) [ 1 ]やDylanなどのオブジェクト指向プログラミングシステムでは、ジェネリック関数は同じ名前を持つすべてのメソッドで構成されるエンティティです。通常、ジェネリック関数は、関数と標準オブジェクトの両方を継承するクラスのインスタンスです。したがって、ジェネリック関数は、関数(引数とともに呼び出し、引数に適用できる)と通常のオブジェクトの両方です。書籍「The Art of the Metaobject Protocol」では、CLOS ジェネリック関数の実装と使用法について詳しく説明しています。
Lispの初期のオブジェクト指向プログラミング拡張機能の1つにFlavorsがあります。これはSmalltalkの影響を受けた一般的なメッセージ送信パラダイムを使用しています。Flavorsでメッセージを送信するための構文は次のとおりです。
(送信オブジェクト:メッセージ)New Flavorsでは、メッセージを実際の関数とし、通常の関数呼び出し構文を使用することが決定されました。
(メッセージオブジェクト)message は汎用関数であり、それ自体がオブジェクトであり関数です。メッセージの個々の実装はメソッドと呼ばれます。
同じアイデアはCommonLoopsにも実装されました。[ 2 ] New Flavors と CommonLoops は Common Lisp オブジェクト システムの主な影響源となりました。
object-1とobject-2という2つのパラメータを持つ汎用関数を定義します。汎用関数の名前はcollideです。
( defgeneric collide ( object-1 object-2 ))汎用関数に属するメソッドは、クラスの外で定義されます。ここでは、汎用関数collideのメソッドを定義します。このメソッドは、クラスasteroid(最初のパラメータobject-1)とクラスspaceship(2番目のパラメータobject-2)に特化されています。パラメータは、メソッド本体内で通常の変数として使用されます。クラススロットにアクセスできる特別な名前空間はありません。
( defmethod collide (( object-1 asteroid ) ( object-2 spaceship )) ( format t "asteroid ~a collides with spaceship ~a" object-1 object-2 ))汎用関数を呼び出す:
? ( collide ( make-instance 'asteroid ) ( make-instance 'spaceship ))小惑星# <ASTEROID 4020003FD3>が宇宙船# <SPACESHIP 40200048CB>と衝突しますCommon Lisp では、汎用関数から個々のメソッドを取得することもできます。FIND-METHOD は、汎用関数collideから、クラスasteroidとspaceshipに特化したメソッドを検索します。
? ( find-method #' collide nil ( list ( find-class 'asteroid ) ( find-class 'spaceship ))) # <STANDARD-METHOD COLLIDE NIL ( ASTEROID SPACESHIP ) 4150015E43>汎用関数は、 Smalltalkのメソッドにほぼ相当しますが、Smalltalk では、どのコードが呼び出されるかはレシーバーのクラスのみによって決定され、引数の型や値は関係ない(シングルディスパッチ)という点が大きな違いです。マルチディスパッチを備えたプログラミング言語では、汎用関数が呼び出されると、メソッドディスパッチは特権を持つ引数だけでなく、すべての引数に基づいて行われます。New Flavorsも汎用関数を提供しましたが、シングルディスパッチのみでした。
JavaScriptにおいて、ジェネリック関数とは、特定の型ではなく、様々な型の値を扱うことができる関数です。これは、型パラメータを使用するか、操作対象の値の型を動的にチェックすることで実現されます。JavaScriptにおけるジェネリック関数の一般的な用途の一つは、配列、文字列、オブジェクトなど、様々なデータ型を扱うことができる再利用可能な関数を作成することです。JavaScriptの動的型付けシステムは、必要に応じて値を容易に型変換できるため、ジェネリック関数の作成に特に適しています。