演算子のオーバーロード

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

コンピュータプログラミングでは演算子のオーバーロード(演算子アドホック多相と呼ばれることもあります)は、ポリモーフィズムの特定のケースであり、さまざまな演算子の実装が引数に応じて異なります。演算子のオーバーロードは、通常、プログラミング言語プログラマー、またはその両方によって定義されます。

理論的根拠

演算子のオーバーロードはシンタックスシュガーであり、ターゲットドメインに近い表記法を使用したプログラミングを可能にし[1]、言語に組み込まれたタイプと同様のレベルの構文サポートをユーザー定義タイプに許可するために使用されます。たとえば、科学計算では、数学オブジェクトの計算表現を紙と同じ構文で操作できるのが一般的です。

演算子のオーバーロードは、関数呼び出しを使用してエミュレートできるため、言語(関数を含む)の表現力を変更しません。たとえば、変数abおよび行列cなどのユーザー定義型について考えてみます。

a + b * c

演算子のオーバーロードをサポートする言語で、「*」演算子が「+」演算子よりも優先されるという通常の仮定では、これは簡潔な記述方法です。

Add(a, Multiply(b, c))

ただし、前者の構文は一般的な数学的使用法を反映しています。

この場合、加算演算子はオーバーロードされ、 C ++のユーザー定義型Timeに加算できるようになります。

時間演算子+ const Time lhs const Time rhs {       
  時間温度= lhs ;   
  temp + = rhs ;  
  temp + = temp / 60 ;    
  temp %= 60 ;  
  temp + = rhs ;  
  temp 時間+ = temp / 60 ;    
  temp %= 60 ;  
  temp 時間+ = rhs 時間;  
  温度を返す; 
}

加算は二項演算です。つまり、2つのオペランドがあります。C ++では、渡される引数はオペランドであり、tempオブジェクトは戻り値です。

lhsこの操作は、隠しthis引数に置き換えて、クラスメソッドとして定義することもできます。ただし、これにより、左側のオペランドは次の型になりますTime

//冒頭の中括弧の直前の「const」は、| this |を意味します 変更されません。
時間時間::演算子+ const Time rhs const {     
  時間温度= * this ; // |これ| 変更しないでください。コピーを作成してください。temp + = rhs ;     
    
  temp + = temp / 60 ;    
  temp %= 60 ;  
  temp + = rhs ;  
  temp 時間+ = temp / 60 ;    
  temp %= 60 ;  
  temp 時間+ = rhs 時間;  
  温度を返す; 
}

クラスメソッドとして定義された単項演算子は、明白な引数を受け取らないことに注意してください(それはからのみ機能しthisます):

ブール時間::演算子()const {   
  戻り時間== 0 &&== 0 &&== 0 ;           
}

より小さい(<)演算子は、構造またはクラスをソートするためにオーバーロードされることがよくあります。

クラス ペア{ 
 パブリック
  ブール演算子< const Pair p const {     
    if x_ == p。x _ { _    
      y_ < pを返します。y_ ;   
    }
    x_ < pを返します。x_ ;   
  }

 プライベート
  int x_ ; 
  int y_ ; 
};

前の例と同様に、最後の例では、演算子のオーバーロードはクラス内で行われます。C ++では、小なり演算子(<)をオーバーロードした後、標準の並べ替え関数を使用して一部のクラスを並べ替えることができます。

批判

演算子のオーバーロードは、プログラマーがオペランドのタイプに応じて演算子のセマンティクスを再割り当てできるため、しばしば批判されてきました[2] 。たとえば、C ++<<で演算子を使用すると、が整数型の場合、変数のビットがビットにシフトしますが、が出力ストリームの場合、上記のコードはストリームにaを書き込もうとします。演算子のオーバーロードにより、元のプログラマーは演算子の通常のセマンティクスを変更し、後続のプログラマーを驚かせることができるため、演算子のオーバーロードを慎重に使用することをお勧めします(Javaの作成者はこの機能を使用しないことにしました[3]。 a << bababab必ずしもこの理由ではありませんが)。

演算子に関するもう1つのより微妙な問題は、数学の特定の規則が誤って予期されたり、意図せずに想定されたりする可能性があることです。たとえば、+の可換性(つまり、a + b == b + a)は常に適用されるわけではありません。+は通常、文字列の連結を実行するためにオーバーロードされるため(つまり、 "bird" + "song"yields "birdsong""song" + "bird"yields "songbird")、オペランドが文字列の場合にこの例が発生します。この議論に対する典型的な反論[要出典]は数学から直接得られます。+は整数(およびより一般的には任意の複素数)では可換ですが、他の「型」の変数では可換ではありません。実際には、+は常に結合的であるとは限りませんたとえば、丸め誤差による浮動小数点値の場合。別の例:数学では、乗算は実数と複素数では可換ですが、行列乗算では可換ではありません。

カタログ

いくつかの一般的なプログラミング言語の分類は、それらの演算子がプログラマーによってオーバーロード可能かどうか、および演算子が事前定義されたセットに制限されているかどうかに従って行われます。

演算子 オーバーロード不可 オーバーロード可能
新しい定義可能[4]
限定セット

演算子のオーバーロードのタイムライン

1960年代

ALGOL 68仕様では、演算子のオーバーロードが許可されていました。[44]

オーバーロードされた演算子¬、=、≠、およびabsが定義さ れているALGOL 68言語仕様(177ページ)からの抜粋:

10.2.2。ブールオペランドの演算
a)op∨ =(bool a、b)bool :( a | true | b);
b)op∧ =(bool a、b)bool:(a | b | false);
c)op¬ =(bool a)bool:(a | false | true);
d)op = =(bool a、b)bool:(a∧b)∨(¬b∧¬a);
e)op ≠=(bool a、b)bool:¬(a = b);
f)op  abs =(bool a)int:(a | 1 | 0);

演算子をオーバーロードするために特別な宣言は必要なく、プログラマーは新しい演算子を自由に作成できることに注意してください。

1980年代

Adaは、Ada 83言語標準の公開により、最初から演算子のオーバーロードをサポートしています。ただし、言語設計者は、新しい演算子の定義を除外することを選択しました。「+」、「*」、「&」などの識別子を使用して新しい関数を定義することにより、言語の現存する演算子のみがオーバーロードできます。その後の言語の改訂(1995年および2005年)では、現存する演算子のオーバーロードに対する制限が維持されます。 。

C ++では、演算子のオーバーロードはALGOL68よりも洗練されています。[45]

1990年代

Sun MicrosystemsのJava言語設計者は、オーバーロードを省略することを選択しました。[46] [47] [48]

Rubyでは、単純なメソッド呼び出しの構文糖衣構文として演算子のオーバーロードが可能です。

Luaでは、メソッド呼び出しの構文シュガーとして演算子のオーバーロードが可能であり、最初のオペランドでその演算子が定義されていない場合は、2番目のオペランドのメソッドが使用されるという機能が追加されています。

2000年代

Microsoftは、2001年にC#に、2003年にVisual Basic.NETに演算子のオーバーロードを追加しました。

Scalaはすべての演算子をメソッドとして扱うため、プロキシによる演算子のオーバーロードが可能になります。

Rakuでは、すべての演算子の定義が字句関数に委任されるため、関数定義を使用して、演算子をオーバーロードしたり、新しい演算子を追加したりできます。たとえば、Rakudoソースで「+」を使用してDateオブジェクトをインクリメントするために定義されている関数は次のとおりです。

multi  infix:<+>Date:D  $ dInt:D  $ x){
     Datenew-from-daycount$ d。daycount + $ x
}

「multi」が使用されたため、関数はマルチディスパッチ候補のリストに追加され、「+」は関数シグネチャの型制約が満たされた場合にのみオーバーロードされます。オーバーロードの容量には、+*> =接尾辞と項iなどが含まれますが、さまざまな中括弧演算子 " [ x、y ] "、 "x [ y ] "、 "x { y } "、および" x y "。

Kotlinは、作成以来、演算子のオーバーロードをサポートしてきました。

も参照してください

参考文献

  1. ^ Stroustrup、Bjarne「演算子のオーバーロード」C ++ FAQ2011年8月14日にオリジナルからアーカイブされました2020年8月27日取得
  2. ^ フィッシャー、チャールズN.(2008)。「オーバーロードの問題」(PDF)ウィスコンシン大学マディソン校
  3. ^ 「これ以上の演算子のオーバーロードはありません」Java言語環境OracleCorporation
  4. ^ 完全に新しい演算子を追加できます。
  5. ^ シンボリック名の2進関数は、中置と呼ぶことができます。
  6. ^ 「述語op / 3」
  7. ^ ハント、ジョン(2012年12月6日)。Smalltalkとオブジェクト指向:はじめに。シュプリンガーサイエンス&ビジネスメディア。ISBN 978-1-4471-0961-7
  8. ^ 「BertrandMeyer:基本的なEiffel言語メカニズム」se.ethz.ch。_ 2021年4月7日取得
  9. ^ 「F90の演算子関数」www.mathcs.emory.edu 2021年4月7日取得{{cite web}}:CS1 maint:url-status(link
  10. ^ Fortran90で導入されました。
  11. ^ 「3。言語リファレンス— Futhark0.19.0ドキュメント」futhark.readthedocs.io 2020年10月10日取得
  12. ^ スミス、クリス(2012年10月9日)。プログラミングF#3.0:複雑な問題を解決するための単純なコードを書くための包括的なガイドO'Reilly Media、Inc。ISBN 978-1-4493-2604-3
  13. ^ オーバーロードの代わりにクラスを入力します。
  14. ^ 「ioガイド」iolanguage.org 2021年4月7日取得
  15. ^ 「演算子」
  16. ^ 「演算子-一言で言えばR、第2版[本]」www.oreilly.com 2021年4月7日取得
  17. ^ 「演算子の作成」
  18. ^ 「演算子」Scalaのツアー
  19. ^ 「Seed7マニュアル:構造化構文の定義」seed7.sourceforge.net 2020年9月29日取得
  20. ^ 「Swift:高度な演算子」
  21. ^ 「Goがメソッドと演算子のオーバーロードをサポートしないのはなぜですか?」2011年9月4日取得
  22. ^ 「はじめに」freepascal.org 2020年9月30日取得
  23. ^ 「オペレーターの過負荷」2018年9月28日取得
  24. ^ 「6.6演算子のオーバーロード」注釈付きAdaリファレンスマニュアル
  25. ^ ドレイトン、ピーター; アルバハリ、ベン; ニューアード、テッド(2003)。一言で言えばC#O'Reilly Media、Inc。ISBN 978-0-596-00526-9
  26. ^ 「C ++演算子のオーバーロード」
  27. ^ 「EclipseCeylon:OperatorPolymorphism」ceylon-lang.org 2021年4月7日取得
  28. ^ 「演算子のオーバーロード-Dプログラミング言語」dlang.org 2020年10月10日取得
  29. ^ 「ダート言語のツアー」dart.dev 2020年9月30日取得
  30. ^ 「演算子のオーバーロード」bourabai.kz 2021年4月7日取得
  31. ^ 「ApacheGroovyプログラミング言語-演算子」groovy-lang.org 2020年9月30日取得
  32. ^ 「演算子のオーバーロード」マニホールド2020年6月7日取得
  33. ^ 「演算子のオーバーロード」Kotlin 2018年6月24日取得
  34. ^ 「Metamethodsチュートリアル」Lua-ユーザーWiki
  35. ^ 「あなたのクラスのための演算子の実装」2013年10月1日取得
  36. ^ 「演算子のオーバーロード」無料のPascalマニュアル2014年12月1日取得
  37. ^ 「演算子のオーバーロード」Delphiマニュアル2014年12月1日取得
  38. ^ 「クラスプロパティをオーバーライドするPHPマジックメソッド」2016年3月4日にオリジナルからアーカイブされました2015年4月7日取得
  39. ^ Orwant、Jon(2002年11月4日)。コンピュータサイエンスとPerlプログラミング:PerlジャーナルのベストO'Reilly Media、Inc。pp。347–。ISBN 978-0-596-00310-4
  40. ^ 「3。データモデル」Python言語リファレンス
  41. ^ 「メソッド」公式RubyFAQ
  42. ^ 「演算子のオーバーロード」例による錆
  43. ^ 「方法:演算子を定義する(Visual Basic)」
  44. ^ Wijngaarden、Adriaan ; Mailloux、Barry J .; ペック、ジョンEL ; コスター、コルネリスHA ; etal。(1968年8月)。「アルゴリズム言語ALGOL68、セクション10.2.2に関するレポート」(PDF)2007年4月1日取得
  45. ^ Stroustrup、Bjarne「C ++の歴史:1979-1991」(PDF)p。12 2007年4月1日取得
  46. ^ 「FAQ質問6.9:なぜ演算子のオーバーロードがないのですか?」comp.lang.javaFAQリスト
  47. ^ "java.sun.com"2009年3月7日にオリジナルからアーカイブされました2009年3月26日取得
  48. ^ ホルツナー、スティーブン(2001)。C ++:ブラックブックアリゾナ州スコッツデール:Coriolisグループ。p。387. ISBN 1-57610-777-9C ++ OOPの最も優れた機能の1つは、演算子をオーバーロードしてクラスのオブジェクトを処理できることです(Javaなどの他のOOP中心の言語ではこれを行うことはできません)。