(翻訳)Scalaでの演算子のオーバーロード

画像



演算子をオーバーロードする能力が特定の言語の長所か短所かについては、長い間議論することができます。 しかし、事実は残っています-Scalaにはそのような機会があります。 それでは、なぜそれを使用しないのですか?



この記事は、主に初心者のScala開発者を対象としています。



オペレーターの過負荷



では、演算子のオーバーロードとは正確には何ですか?

一般に、演算子はおなじみの「+」、「-」、「*」、「!」です。 その他多数。 さらに、同じ演算子は、操作対象に応じて異なる動作をする場合があります(たとえば、+は整数の合計を取得し、+は文字列連結操作として使用されます)。 演算子のオーバーロードの考え方は単純です-演算子の動作が、それが動作するオブジェクトのクラスに応じて変化する場合、そのクラスに対して具体的に新しい動作を定義してみませんか?



ちょっと待って! しかし、彼らはオペレーターのオーバーロードは悪だと私に言った!


演算子のオーバーロードは、かなり物議を醸すトピックです。 これは多くの悪用の原因であるとよく言われますが、この機能はC ++で中傷されたため、Java言語の作成者は意図的にそれを放棄しました(文字列を連結する+演算子を除く)。



私は少し異なる意見を持っています。 適切な責任を持ってオペレーターの過負荷に近づくと、大きな実用的な利点を引き出すことができます。 例を挙げましょう:多くのオブジェクトを一緒に追加したり追加したりすることができます。なぜ「+」演算子を使用しないのですか?



複素数のクラスを作成し、複素数を追加したいとします。 次のコードを書く方が快適ではありませんか?



Complex result = complex1 + complex2;





...より...

Complex result = complex1.add(complex2);







最初の行はより自然に見えますよね?



それでは、Scalaは演算子のオーバーロードを許可していますか?





そうでもない。 より正確には、いいえ。



その前に読んだものはすべてナンセンスであることがわかりました。 これは私が今まで読んだ中で最も愚かな記事です! 私はScalaが嫌いです。 Algol 68でのプログラミングの継続を改善します。




ちょっと待ってください、まだ終わっていません。 Scalaは演算子のオーバーロードをサポートしていません。Scalaには単純にオーバーロードがないためです!



Scalaには演算子はありませんか? あなたはクレイジーです! 何度も「sum = 2 + 3」のようなものを書きました! しかし、リストの「::」と「:/」の操作はどうですか? 彼らは演算子のように見えます!




悲しいかな、そうではありません。 全体のポイントは、Scalaにはメソッドと呼ばれるものに対する厳密な要件がないことです。



次のコードを書くとき:



sum = 2 + 3





...実際には、インスタンスのRichIntクラスの+メソッドを値2で呼び出します。最後の行を次のように書き換えることもできます。

sum = 2.+(3)





...本当にしたい場合。



うん。 わかった。 そこで、オペレータのオーバーロードについて教えてください。




それは非常に単純です-通常のメソッドを記述するのと同じくらい簡単です。 例を挙げましょう。



 class Complex(val real : Double, val imag : Double) { def +(that: Complex) = new Complex(this.real + that.real, this.imag + that.imag) def -(that: Complex) = new Complex(this.real - that.real, this.imag - that.imag) override def toString = real + " + " + imag + "i" } object Complex { def main(args : Array[String]) : Unit = { var a = new Complex(4.0,5.0) var b = new Complex(2.0,3.0) println(a) // 4.0 + 5.0i println(a + b) // 6.0 + 8.0i println(a - b) // 2.0 + 2.0i } }
      
      







これはすべてクールですが、演算子「not」(「!」)を再定義する場合はどうでしょうか。




この演算子と「+」および「-」演算子の違いは、単項および接頭辞であるということです。 ただし、Scalaは、「+」などの挿入演算子よりも限定された形式でこのような機能もサポートしています。



限定された形式とは、単項接頭辞演算子「+」、「-」、「!」の4つしか再定義できないという事実を意味します。 および「〜」。 これを行うには、クラスで適切なメソッドunary_!、unary_〜などを定義する必要があります。



次の例は、この数値のモジュラスを返す複素数の〜演算子を定義する方法を示しています。



 class Complex(val real : Double, val imag : Double) { // ... def unary_~ = Math.sqrt(real * real + imag * imag) } object Complex { def main(args : Array[String]) : Unit = { var b = new Complex(2.0,3.0) prinln(~b) // 3.60555 } }
      
      







結論として


ご覧のとおり、Scalaの演算子のオーバーロードは非常に簡単です。 しかし、この機会を賢く使ってください。 クラスが加算または加算として解釈できる何かを実行できる場合を除き、クラスで「+」などのメソッドを定義しないでください。



オリジナル記事-Tom Jefferys、Scalaの「Operator Overloading」



All Articles