ポリモーフィズム(コンピューターサイエンス)

ウィキペディアから、無料の百科事典
ナビゲーションにジャンプ 検索にジャンプ

プログラミング言語型理論ではポリモーフィズムとは、異なるタイプのエンティティへの単一のインターフェイスの提供[1] 、または複数の異なるタイプを表すための単一のシンボルの使用です。[2]この概念は、生物または種が多くの異なる形態または段階を持つことができる生物学の原理から借用されています。[3]

多型の最も一般的に認識されている主要なクラスは次のとおりです。

  • アドホック多相性:個別に指定された型の任意のセットに共通のインターフェースを定義します。
  • パラメトリックポリモーフィズム:1つ以上の型が名前ではなく、任意の型を表すことができる抽象記号によって指定されている場合。
  • サブタイピング(サブタイプポリモーフィズムまたは包含ポリモーフィズムとも呼ばれます):名前が、いくつかの一般的なスーパークラスによって関連付けられた多くの異なるクラスのインスタンスを示す場合。[4]

歴史

ポリモーフィック型システムへの関心は1960年代に大幅に発展し、10年の終わりまでに実用的な実装が登場し始めました。 アドホック多相性パラメトリック多相性は、もともとクリストファー・ストレイチーのプログラミング言語の基本概念[5]で説明されており、多相性の「2つの主要なクラス」としてリストされています。アドホック多相はAlgol68の機能でしたが、パラメトリック多相はMLの型システムのコア機能でした。

1985年の論文で、PeterWegnerLucaCardelliは、サブタイプと継承モデル化するために包含ポリモーフィズムという用語を導入し[2]、それを実装する最初のプログラミング言語として Simulaを引用しました。

タイプ

アドホック多相

Christopher Stracheyは、アドホック多相性という用語を選択して、さまざまなタイプの引数に適用できるが、適用される引数のタイプに応じて動作が異なる多相関数を指します(関数のオーバーロードまたは演算子のオーバーロードとも呼ばれます)。[5]この文脈での「アドホック」という用語は、蔑称的であることを意図していません。これは、このタイプのポリモーフィズムが型システムの基本的な機能ではないという事実を単に指します。以下のPascal / Delphiの例では、Add関数は、呼び出しを見るとさまざまなタイプで一般的に機能しているように見えますが、コンパイラーはすべての目的と目的で2つの完全に異なる関数と見なします。

プログラム アドホック;

関数 Add x  y   整数  整数; 
開始
    追加 :=  x  +  y
終了;

関数 Add s  t   String   String ; 
begin 
    Add  :=  Concat s  t 
end ;


    Writeln開始しますAdd 1、2 )); (* "3"を出力します*)Writeln Add 'Hello、' 'Mammals!' )); (*「Hello、Mammals!」を出力します*)end                     
         

動的型付け言語では、呼び出す必要のある正しい関数は実行時にしか判別できない可能性があるため、状況はより複雑になる可能性があります。

暗黙の型変換は、「強制ポリモーフィズム」と呼ばれるポリモーフィズムの形式としても定義されています。[2] [6]

パラメトリック多型

パラメトリックポリモーフィズムを使用すると、関数またはデータ型を一般的に記述できるため、型に依存せずに値を均一に処理できます。[7]パラメトリックポリモーフィズムは、完全な静的型安全性を維持しながら、言語をより表現力豊かにする方法です。

パラメトリック多相の概念は、データ型関数の両方に適用されます。さまざまなタイプの値に評価または適用できる関数は、ポリモーフィック関数と呼ばれます。一般化されたタイプのように見えるデータ型(たとえば、任意のタイプの要素を含むリスト)は、そのような特殊化が行われる一般化されたタイプと同様に、 ポリモーフィックデータ型として指定されます。

パラメトリックポリモーフィズムは関数型プログラミングに遍在しており、単に「ポリモーフィズム」と呼ばれることがよくあります。Haskellの次の例は、パラメーター化されたリストデータ型とそれらの2つのパラメトリックポリモーフィック関数を示しています。

データ リスト a  =  Nil  |  短所 a  リスト a 

長さ :: リスト a- >整数 長さNil = 0長さCons x xs = 1+長さxs 
           
        

map   :(a-  >  b  -> リスト a-  > リスト b 
map  f  Nil          =  Nil 
map  f  Cons  x  xs  =  Cons  f  x  map  f  xs 

パラメトリックポリモーフィズムは、いくつかのオブジェクト指向言語でも利用できます。たとえば、C ++とDのテンプレート、またはC#、Delphi、Java のジェネリックという名前のテンプレート:

クラス リスト< T >  {
    クラス ノード< T >  { 
        T  elem ; 
        ノード< T > ; 
    }
    ノード< T > ヘッド; 
    int  length () {  ...  } 
}

リスト< B > マップFunc < A  B >  f  リスト<A> xs { ... } _ _  
    

John C. Reynolds(および後にJean-Yves Girard)は、ラムダ計算(多形ラムダ計算またはシステムFと呼ばれる)の拡張として、このポリモーフィズムの概念を正式に開発しました。パラメトリシティポリモーフィック関数は、データの値ではなくデータの形状に作用して、実行できることを必然的に制限し、パラメトリシティの概念につながります。

サブタイピング

一部の言語では、サブタイピング(サブタイプポリモーフィズムまたは包含ポリモーフィズムとも呼ばれます)の概念を使用して、ポリモーフィズムの特定の場合に使用できるタイプの範囲を制限しています。これらの言語では、サブタイピングにより、特定のタイプTのオブジェクトを取得するように関数を記述できますが、 TのサブタイプであるタイプSに属するオブジェクトが渡された場合は、正しく機能しますリスコフの置換原則に従って) 。このタイプの関係は、S  <:  Tと書かれることもあります。逆に、TはSのスーパータイプあると言われています-書かれたT  >  S。サブタイプのポリモーフィズムは通常、動的に解決されます(以下を参照)。

次の例では、猫と犬を動物のサブタイプにします。この手順letsHear()は動物を受け入れますが、サブタイプが動物に渡された場合にも正しく機能します。

抽象 クラス Animal  {
    抽象 文字列 トーク(); 
}

class  Cat  extends  Animal  { 
    String  talk () { 
        return  "Meow!" ; 
    } 
}

class  Dog  extends  Animal  { 
    String  talk () { 
        return  "Woof!" ; 
    } 
}

static  void  letsHear final  Animal  a  { 
    println a .talk ( )); }


static  void  main String []  args  { 
    letsHear new  Cat ()); 
    LetsHear 新しい ()); 
}

別の例では、NumberRational、およびIntegerNumber  :>  RationalおよびNumber  :>  Integerのような型である場合、 Numberを受け取るように記述された関数は、 IntegerまたはRationalを渡すと、Numberを渡す場合と同じように機能します。オブジェクトの実際のタイプは、クライアントからブラックボックスに隠して、オブジェクトIDを介してアクセスできます実際、Numberタイプが抽象である場合、そのオブジェクトを手に入れることさえできない場合があります。最も派生した型はNumberです(抽象データ型抽象クラスを参照)。この特定の種類の型階層は、特にSchemeプログラミング言語のコンテキストでは、数値タワーとして知られており、通常、さらに多くの型が含まれています。

オブジェクト指向プログラミング言語は、サブクラス化(継承とも呼ばれます)を使用してサブタイプポリモーフィズムを提供します通常の実装では、各クラスにはいわゆる仮想テーブル(クラスインターフェイスのポリモーフィック部分を実装する関数のテーブル)が含まれ、各オブジェクトにはそのクラスの「vtable」へのポインタが含まれ、ポリモーフィックが参照されるたびに参照されます。メソッドが呼び出されます。このメカニズムは次の例です。

  • 仮想関数呼び出しは呼び出し時までバインドされないため、遅延バインディング。
  • 単一ディスパッチ(つまり、単一引数のポリモーフィズム)。仮想関数呼び出しは、最初の引数(オブジェクト)によって提供されるvtableを調べるだけでバインドされるthisため、他の引数の実行時の型は完全に無関係です。

同じことが他のほとんどの一般的なオブジェクトシステムにも当てはまります。ただし、Common Lisp Object Systemなどの一部は、複数のディスパッチを提供します。この場合、メソッド呼び出しはすべての引数でポリモーフィックです。

パラメトリック多型とサブタイピングの間の相互作用は、分散有界量化の概念につながります。

行多相

行多相[8]は似ていますが、サブタイピングとは異なる概念です。構造型を扱います残りの型情報を失うことなく、型が特定のプロパティを持つすべての値を使用できます。

ポリタイピズム

関連する概念は、ポリタイプ(またはデータ型の汎用性)です。ポリモーフィック関数はポリモーフィックよりも一般的であり、そのような関数では、「特定のデータ型に対して固定のアドホックケースを提供できますが、アドホックコンビネータはありません」。[9]

実装の側面

静的および動的ポリモーフィズム

ポリモーフィズムは、実装が選択されたときによって区別できます。静的(コンパイル時)または動的(実行時、通常は仮想関数を介して)。これは、それぞれ静的ディスパッチおよび動的ディスパッチ呼ばれ、対応するポリモーフィズムの形式は、静的ポリモーフィズムおよび動的ポリモーフィズムと呼ばれます。

動的ディスパッチのオーバーヘッドがないため、静的ポリモーフィズムはより高速に実行されますが、追加のコンパイラサポートが必要です。さらに、静的ポリモーフィズムにより、コンパイラー(特に最適化のため)、ソースコード分析ツール、および人間のリーダー(プログラマー)によるより優れた静的分析が可能になります。ダイナミックポリモーフィズムはより柔軟ですが低速です。たとえば、ダイナミックポリモーフィズムではダックタイピングが可能であり、ダイナミックリンクライブラリはオブジェクトの完全なタイプを知らなくてもオブジェクトを操作できます。

静的多相は通常、アドホック多相とパラメトリック多相で発生しますが、動的多相はサブタイプ多相では通常発生します。ただし、テンプレートメタプログラミング、つまり不思議なことに繰り返されるテンプレートパターンをより高度に使用することで、サブタイピングを使用して静的なポリモーフィズムを実現することができます

ポリモーフィズムがライブラリを介して公開されると、共有オブジェクトが構築されるときにパラメータがどのタイプであるかを知る方法がないため、ダイナミックライブラリでは静的ポリモーフィズムが不可能になります。C ++やRustなどの言語は単相化されたテンプレートを使用ますが、Swiftプログラミング言語は動的ディスパッチを広範囲に使用して、デフォルトでこれらのライブラリのアプリケーションバイナリインターフェイスを構築します。その結果、実行時のオーバーヘッドを犠牲にして、より多くのコードを共有してシステムサイズを削減できます。[10]

も参照してください

参考文献

  1. ^ Bjarne Stroustrup(2007年2月19日)。「BjarneStroustrupのC ++用語集」ポリモーフィズム–さまざまなタイプのエンティティに単一のインターフェイスを提供します。
  2. ^ a b c Cardelli、Luca ; ウェグナー、ピーター(1985年12月)。「タイプ、データの抽象化、およびポリモーフィズムの理解について」(PDF)ACMコンピューティング調査17(4):471–523。CiteSeerX10.1.1.117.695_ 土井10.1145 /6041.6042S2CID2921816_   :「ポリモーフィック型は、その操作が複数の型の値に適用できる型です。」
  3. ^ 「ポリモーフィズム」Java™チュートリアル:Java言語の学習:インターフェースと継承Oracle 2021-09-08を取得しました。
  4. ^ Conallen、J。; Engle、M。; ヒューストン、K。; Maksimchuk、R。; ヤング、B。; ブーチ、G。(2007)。アプリケーションを使用したオブジェクト指向の分析と設計(第3版)。ピアソン教育。ISBN 9780132797443
  5. ^ a b Strachey、クリストファー(2000)。「プログラミング言語の基本概念」。高次および記号計算13(1/2):11–49。CiteSeerX10.1.1.332.3161_ 土井10.1023 / A:1010000313106ISSN1573-0557_ S2CID14124601_   
  6. ^ タッカー、アレンB.(2004)。コンピュータサイエンスハンドブック(第2版)。テイラーアンドフランシス。pp。91–。ISBN 978-1-58488-360-9
  7. ^ ピアス、BC(2002)。「23.2ポリモーフィズムの品種」タイプとプログラミング言語MITプレス。pp。340–1。ISBN 9780262162098
  8. ^ ワンド、ミッチェル(1989年6月)。「レコードの連結と多重継承のための型推論」。議事録。コンピュータサイエンスにおける論理に関する第4回年次シンポジウムpp。92–97。土井10.1109 /LICS.1989.39162
  9. ^ Lämmel、ラルフ; Visser、Joost(2002)。「ジェネリックトラバーサル用の型付きコンビネータ」。宣言型言語の実用的側面:第4回国際シンポジウムスプリンガー。pp。137–154、p。153. CiteSeerX10.1.1.18.5727_ ISBN  354043092X
  10. ^ Beingessner、Alexis。「SwiftがRustができなかったダイナミックリンクをどのように達成したか」

外部リンク