なんですが、イマイチそれだけ言われても実感できないので、
試してみました。
ついでにリッチラッパーの確認もやってました。
サンプルコード
■OperatorMethodMain.scala
package jp.gr.kmtn.scalatutorial.grammertips
/**
* 演算子/メソッド共通確認+リッチラッパー確認テスト用メインクラス
*
* @author Fukushi-
*/
object OperatorMethodMain {
/**
* 演算子/メソッド共通確認+リッチラッパー確認テスト用プログラムエントリポイント
*/
def main(args: Array[String]): Unit =
{
// 演算子動作確認
val two = 2
val five = 5
val nine = 9
// 演算子表現確認
Console.println("---Case 1-1 ---")
Console.println(two + five)
Console.println(nine - five)
// メソッド表現確認
Console.println("---Case 1-2 ---")
Console.println(two.+(five))
Console.println(nine.-(five))
// メソッド動作確認
val str = "Two,Five,Nine"
// 演算子表現確認
Console.println("---Case 2-1 ---")
val strArray = str split ","
strArray.foreach(Console.println(_))
// メソッド表現確認]
Console.println("---Case 2-2 ---")
str.split(",").foreach(Console.println(_))
// リッチラッパー用メソッド確認
Console.println("---RichWrapper ---")
Console.println(nine max five)
Console.println(nine.max(five))
}
}
実行結果
で、実行結果は下記のようになります。
---Case 1-1 ---
7
4
---Case 1-2 ---
7
4
---Case 2-1 ---
Two
Five
Nine
---Case 2-2 ---
Two
Five
Nine
---RichWrapper ---
9
9
コード解説
上のCase1-Xから見ていきましょう。
Case1-1ではInt型の変数を + で連結して加算を行っています。
Case1-2では、Int型変数のメソッド「+」を呼び出して加算を行っています。
Console.println(two + five) → Case1-1、「+」を演算子形式で記述
Console.println(two.+(five)) → Case1-2、「+」をメソッド形式で記述
Case1-1と、Case1-2の表現は等価です。
つまり、演算子のように見える「+」もメソッドでしかないことがわかりますね。
後、実際にInt型変数のメソッド一覧(Eclipseの補完一覧)を見てみると
演算子と同じメソッドが存在していることがわかります。
次は、Case2-Xの説明です。
Case1-Xとは逆に、splitメソッドを演算子形式で記述しています。
val strArray = str split "," → Case2-1、「split」を演算子形式で記述
val printArray = str.split(",") → Case2-2、「split」をメソッド形式で記述
Case2-1、Case2-2の表現も等価です。
つまりはScalaでは下記の2つのことが言える、となりますね。
1.演算子は存在せず、全てメソッドで構成されている
2.メソッドはJavaでいう演算子形式と、メソッド形式のどちらでも記述可能
Javaと書き方自体は変えずに、背後で動く機構は統一されているようですね。なかなか新鮮。
後、最後にリッチラッパーについて。
下記のコードで、Int型に対してmaxというメソッドを使用しています。
Console.println(nine max five)
Console.println(nine.max(five))
なんですが、Int型にはmaxというメソッドは存在しません。
maxというメソッドが定義されているのは、「scala.runtime.RichInt」というクラスです。
下記のコードの中で、maxメソッド実行時に暗黙の型変換(Int→RichInt)がおこなわれてるため、
Int型の変数が直接maxメソッドを呼び出せるようです。
どういう仕組みなのかなぁ。。と思ってみてクラス構造を見てみた所、
「scala.runtime.ScalaNumberProxy」、「scala.runtime.ScalaNumberProxy」クラスが
リッチラッパーに絡んでいる模様。
更に背後には、「scala.Proxy」トレイトや、「scala.Proxy.Typed」トレイトが絡んでいる模様。
自分で今回のリッチラッパーのように既存のクラスに対して機能を追加できる、
追加機能の実行時にのみ暗黙的に型変換されるため
余計な考慮は不要というコードが作れたら面白そうですよね。
ただ、それについてはまたの機会に。
0 コメント:
コメントを投稿