Javaプログラマー向けのKotlinについて

この記事では、Kotlinプログラミング言語について説明します。 プロジェクトの外観の理由、言語の可能性について学び、いくつかの例を参照します。 この記事は、主に読者がJavaプログラミング言語に精通していることを期待して書かれましたが、別の言語を知っている人もこのテーマについてのアイデアを得ることができます。 この記事は表面的なものであり、javascriptでのコンパイルに関連する問題を扱っていません。 プロジェクトの公式ウェブサイトで完全なドキュメントを見つけることができますが、簡単に言語について話そうとします。



プロジェクトについて



少し前、開発環境の開発者であるJetBrainsは、新製品のKotlinプログラミング言語を発表しました。 批判の波が会社に降りかかった。批評家は、会社が自分の言語を開発する代わりに、気を変えてScalaのプラグインを完成させることを提案した。 Scala開発者は優れた開発環境を実際に欠いていますが、プラグイン開発者の問題を理解することもできます。 。 現時点では、JVMの静的型付けを使用する現代言語のセグメントは小さいため、開発環境と一緒に独自の言語を作成する決定は非常に先見の明があります。 この言語がコミュニティにまったく根付いていない場合でも、JetBrainsは主にそのニーズに対応しています。 Javaプログラマーなら誰でもこれらのニーズを理解できます:Javaは言語として非常にゆっくりと開発され、新しい機能は言語に登場しません(1年以上待っていた1次関数)。将来(たとえば、型の適切なパラメーター化)。 ソフトウェアを開発する会社にとって、プログラミング言語は主要な作業ツールです。したがって、言語の有効性と単純性は、そのためのツールの開発の単純性だけでなく、コーディングに関するプログラマーのコスト、つまりこのコードに付随することの容易さを決定する指標ですそれを理解します。



言語について



言語は静的に型付けされます。 しかし、Javaと比較して、Kotlinコンパイラは、nullを含むリンクの可能性に関する情報を型に追加します。これにより、型チェックが強化され、実行がより安全になります。



fun foo(text:String) { println(text.toLowerCase()) // NPE? ! } val str:String? = null // String? --   null- foo(str) // <-      -- //  str   String,  //    foo
      
      







このアプローチはプログラマーをNPEに関連する多くの問題から救うことができるという事実にもかかわらず、最初はJavaプログラマーにとっては不要に思えます-追加のチェックや変換を行う必要があります。 しかし、Javaに戻ってkotlinでプログラミングを行った後、このタイプ情報が欠落していると感じた場合は、Nullable / NotNullアノテーションの使用を検討してください。 関連するのは、Javaとの下位互換性の問題です。この情報はJavaバイトコードには含まれていませんが、私が知る限り、この質問はまだ解決過程にありますが、現時点ではJavaからのすべての型はNULL可能です。



ところで、後方互換性について:KotlinはJVMバイトコードにコンパイルされ(言語の作成者は互換性サポートに多大な労力を費やします)、Javaと同じプロジェクトで使用できるようになり、javaクラスとKotlinクラスを相互に使用できるため、Kotlinを既存の大きな最小値に統合するためのしきい値が作成されますJavaプロジェクト。 この点で、複数のJava開発を使用できることが重要であり、完全にkotlinでプロジェクトを作成します。 たとえば、spring-webmvcをベースにした小さなプロジェクトを作成することはほとんど難しくありませんでした。



コントローラーのフラグメントを見てみましょう:



 path(array("/notes/")) controller class NotesController { private autowired val notesService : NotesService? = null path(array("all")) fun all() = render("notes/notes") { addObject("notes", notesService!!.all) } //... }
      
      







Kotlinでアノテーションを使用することの特性を見ることができます:Javaのように場所がきれいに見えません(1つの要素の配列などの特別なケースに関係します)が、アノテーションはautowired



controller



(エイリアスを指定する場合)のような「自家製」のキーワードとして使用できますインポート時に入力)、可能性に応じて、アノテーションは実際のクラスに近づきます。



Springはトランザクション管理のためにkotlinクラスをラップできなかったことに注意すべきです-これが将来可能になることを望みます。



この言語は、一流の機能をサポートしています。 これは、関数が特別な構文がある言語に組み込まれた型であることを意味します。 関数をローカルで作成し、パラメーターで他の関数に渡し、それらへのリンクを保存できます。



 fun doSomething(thing:()->Unit) { //     // ()->Unit     //     thing() //  } doSomething() { //        // ()->Unit      doShomething //   --  ,  //      println("Hello world") }
      
      







クラスのカプセル化に違反しないが、このクラスのメソッドとしてアクセスできるメソッドで既存のクラスを拡張できるようにする拡張機能をこの機能に追加すると、アメニティの点ではかなり劣る標準のJavaライブラリ用のかなり強力な拡張メカニズムが得られます。 従来、標準ライブラリに既に存在するリストをフィルタリングする機能を追加します。



 fun <T> List<T>.filter(condition:(T)->Boolean):List<T> { val result = list<T>() for(item in this) { if(condition(item)) result.add(item) } return result } val someList = list(1, 2, 3, 4).filter { it > 2 } // someList==[3, 4]
      
      







変数にはタイプが指定されていないことに注意してください-Kotlinコンパイラーは、可能であればそれらを表示し、インターフェースの明瞭さを妨げません。 一般的に、言語は、キーボードの後ろの人が余分な文字を入力するのを可能な限り節約するように作られています:最小限のキーワードを含む短くても理解可能な構文、式を区切るセミコロンの必要性、タイプ推論、必要に応じて作成する新しいキーワードの欠如クラス-のみ必要です。



クラスと簡潔さのトピックを説明するには、次のコードを見てください。



 //  bean-  // ,    //     class TimeLord(val name:String) //       class TARDIS(val owner:TimeLord) fun main(args:Array<String>) { val doctor = TimeLord("Doctor") val tardis = TARDIS(doctor) println(tardis.owner.name) }
      
      







数行で、2つのクラスを宣言し、2つのオブジェクトを作成し、TARDISの所有者の名前を表示することができました! クラスは、そのプロパティの宣言でもある唯一の可能なコンストラクターのパラメーターで宣言されていることに気付くかもしれません。 非常に短いですが、同時に有益です。 確かに、複数のコンストラクターを宣言できないことを非難する人もいますが、これには独自のプラグマティズムがあるようです-結局のところ、Javaのいくつかのコンストラクターは、Kotlinが言語レベルでサポートするデフォルトパラメーターを宣言するか、あるタイプを別のタイプに変換することを可能にしますこのクラスはこのクラスで機能しますが、これはすでにファクトリメソッドの恩恵で安全に残されています。 「変数」とフィールドの宣言に注意してください。 Kotlinはval



またはvar



選択を強制します。 ここで、val-不変のfinal



リンクを宣言し、var-可変リンクの広範な使用を回避するのに役立つ変数を宣言します。





それで、あなたはすでにもっと面白いことをすることができる場所に着きました。 インタビューでは、ツリーを実装し、その周りを歩き回り、要素を使用して何らかのアクションを決定するタスクを頻繁に行います。 これがkotlinでどのように実装されているか見てみましょう。



だから私は次のように使用したいと思います:



 fun main(args: Array<String>) { //    val tree= tree("root") { node("1-1") { node("2-1") node("2-2") } node("1-2") { node("2-3") } } //        tree.traverse { println(it) } }
      
      







これを実装してみてください。 ツリーノードクラスを作成します。



 /** * @param value   */ class Node<T>(val value:T) { //   private val children:List<Node<T>> = arrayList() /** * ,       * @param value     * @param init    ,  *  */ fun node(value:T, init:Node<T>.()->Unit = {}):Node<T> { val node = Node<T>(value) node.init() children.add(node) return node } /** *          * ,      * @param handler       */ fun traverse(handler:(T)->Unit) { handler(value) children.forEach { child -> child.traverse(handler) } } }
      
      







次に、ツリートップを作成する関数を追加します。



 /** *      value   *    init. */ fun <T> tree(value:T, init:Node<T>.()->Unit): Node<T> { val node = Node(value) //   init,   // ,    node.init() return node }
      
      







コード内の2つの場所で、ビューコンストラクトが使用されました Node.()->Unit, , -, Node. , Node.node(), , .







java , Kotlin java . , .



, , github-, Issue Tracker. , . milestone 3, , , JetBrains, .












Node.()->Unit, , -, Node. , Node.node(), , .







java , Kotlin java . , .



, , github-, Issue Tracker. , . milestone 3, , , JetBrains, .












Node.()->Unit, , -, Node. , Node.node(), , .







java , Kotlin java . , .



, , github-, Issue Tracker. , . milestone 3, , , JetBrains, .















All Articles