後戻りできない:JavaからScalaに切り替えたのに戻ってこない

Javaに対するScalaの長所と短所に関する議論は、C対C ++に関する議論を思い出させます。 プラスはもちろん、より複雑な言語であり、足を踏み入れたり、アプリケーションを落としたり、完全に読めないコードを書いたりする膨大な数の方法があります。 しかし、一方で、C ++の方が簡単です。 これにより、素のCでは難しいものを簡単に作成できます。 この記事では、この言語を産業化したScalaの側面、つまりプログラミングを容易にし、ソースコードを明確にする側面についてお話します。



言語間のさらなる比較は、読者が次のことを熟知しているという事実から得られます。



-Java8。 Lambdのサポートがなければ、話すことは何もありません

-ゲッター、セッター、コンストラクター、ビルダーの長いシートではなく、 ロンボクの短い注釈

- グアバ不変のコレクションと変換

-Java Stream API

-適切なSQLのフレームワークであるため、複数行の文字列のサポートは不要です

-flatMap-マップ、要素を任意の数(0、1、n)の他の要素に置き換えます。



デフォルトの免疫



おそらく誰もが、不変のデータ構造が良いアイデアであることにすでに同意しています。 Scalaでは、 `final`を設定せずに不変のコードを書くことができます



Java
@Value class Model { String s; int i; } public void method(final String a, final int b) { final String c = a + b; }
      
      







スカラ
 case class Model(s: String, i: Int) def method(a: String, b: Int): Unit = { val c: String = a + b }
      
      







コードブロック、条件、スイッチは式であり、演算子ではありません



つまり 上記のすべてが値を返すため、戻り演算子を取り除くことができ、不変データまたは多数のラムダで機能するコードを大幅に簡素化できます。



Java
 final String s; if (condition) { doSomething(); s = "yes"; } else { doSomethingElse(); s = "no" }
      
      







スカラ
 val s = if (condition) { doSomething(); "yes" } else { doSomethingElse(); "no" }
      
      







パターンマッチング、適用解除()および封印されたクラス階層



任意のデータ型で動作し、コンパイル時に警告を表示し、考えられるすべてのケースをカバーしておらず、オブジェクトのフィールドではなく、困難な条件に従って選択を行う方法を知っているスイッチが必要ですか? Scalaで彼は!



スカラ
  sealed trait Shape //sealed trait - ,          case class Dot(x: Int, y: Int) extends Shape case class Circle(x: Int, y: Int, radius: Int) extends Shape case class Square(x1: Int, y1: Int, x2: Int, y2: Int) extends Shape val shape: Shape = getSomeShape() //    Shape val description = shape match { //x  x    -    Dot case Dot(x, y) => "dot(" + x + ", " + y + ")" //Circle,     .       Scala case Circle(x, y, 0) => s"dot($x, $y)" //   10 case Circle(x, y, r) if r < 10 => s"smallCircle($x, $y, $r)" case Circle(x, y, radius) => s"circle($x, $y, $radius)" //       case sq: Square => "random square: " + sq.toString } //        ,   
      
      







Java
私はJavaでそれを繰り返そうとはしません。



構成をサポートするための一連の構文機能



OOPの最初の3つのクジラが(コーラスで言う)カプセル化、ポリモーフィズム、および継承であり、4番目が集約である場合、5番目のクジラは間違いなく関数、ラムダ、およびオブジェクトの構成になります。



Javaの問題は何ですか? 括弧内。 単一行のメソッドを記述したくない場合、ラムダを使用してメソッドを呼び出すときは、メソッド呼び出しの括弧に加えてメソッドをラップする必要があります。



Java
 //         map  flatMap.         . // collection     ,     ,    collection.flatMap(e -> { return getReplacementList(e).map(e -> { int a = calc1(e); int b = calc2(e); return a + b; }); }); withLogging("my operation {} {}", a, b, () -> { //do something });
      
      







スカラ
 collection.flatMap { e => getReplacementList(e).map { e => val a = calc1(e) val b = calc2(e) a + b } } withLogging("my operation {} {}", a, b) { //do something }
      
      







違いは取るに足らないように見えるかもしれませんが、ラムダを大量に使用することで、重要になります。 内部クラスの代わりにラムダを使用するように。 もちろん、これにはラムダの大量使用のために設計された適切なライブラリの可用性が必要ですが、それらは確かに既に存在するか、まもなく利用可能になります。



メソッドパラメータ:名前付きパラメータとデフォルトパラメータ



Scalaでは、メソッドを呼び出すときに引数名を明示的に指定でき、デフォルトの引数値もサポートしています。 ドメインモデル間のコンバーターを作成したことがありますか? これは岩の中の様子です。



スカラ
 def convert(do: PersonDataObject): Person = { Person( firstName = do.name, lastName = do.surname, birthDate = do.birthDate, address = Address( city = do.address.cityShort, street = do.address.street ) )
      
      







パラメーターのセットとそのタイプはコンパイル段階で制御されます。実行時は、コンストラクターの呼び出しにすぎません。 Javaでは、コンストラクター/ファクトリーメソッドの呼び出し(引数の制御の欠如、2つの文字列引数とhelloを適切に混在させる)、またはビルダー(ほぼ適切ですが、オブジェクトの構築時に必要なパラメーターがすべて指定されているという事実は、実行時にのみ確認できます) )



nullおよびNullPointerException



Skalovskyの「オプション」は基本的にJavaの「オプション」と違いはありませんが、上記の機能を使用すると簡単に楽しく作業できますが、Javaではいくつかの努力が必要です。 ロックプログラマーは、null許容フィールドを避けるように強制する必要はありません。ラッパークラスはnullと同じくらい便利です。



スカラ
 val value = optValue.getOrElse("no value") //   "no value" val value2 = optValue.getOrElse { //  exception throw new RuntimeException("value is missing") } val optValue2 = optValue.map(v => "The " + v) //Option("The " + value) val optValue3 = optValue.map("The " + _) //  ,   val sumOpt = opt1.flatMap(v1 => opt2.map(v2 => v1 + v2)) //Option       Option val valueStr = optValue match { //Option -   sealed trait   ! case Some(v) => // -   ,   log.info("we got value {}", v) "value.toString is " + v case None => // -   ,    log.info("we got no value") "no value" }
      
      







もちろん、このリストは完全ではありません。 さらに、それぞれの例は取るに足らないように見えるかもしれません-実際、ラムダを呼び出すときにいくつの括弧を書く必要があるのでしょうか? しかし、ロックの主な利点は、上記のすべてを組み合わせることで得られるコードです。 したがって、java8のjava5は構文の点でそれほど違いはありませんが、一連の小さな変更により、アーキテクチャ計画の新しい可能性を開くなど、開発がはるかに簡単になります。



また、この記事では、この言語の他の強力な(そして危険な)機能、Scalaエコシステム、およびFP全体については取り上げません。 そして、欠陥については何も言われていない(誰が持っていない...)。 しかし、「なぜこのロックが必要なのか」という質問に対して、ジャビストが答えを得て、ロッカーがオンラインバトルで彼らの言語の名誉を守ることができるようになることを願っています)



All Articles