コトリンのキャラクター

こんにちは、Habr! 近い将来、Kotlinに到着したいと考えています。 彼らはこの記事(2月)を通過できませんでした。



読んでコメント!



ブルース・テイトの本「 7週間の7つの言語 」を読み終えたところです。 私はこの本で説明されているほとんどの言語を扱った経験がありますが、著者がどのように言語を特徴づけ、これらの特性が言語の実際の使用に最終的に影響するかがとても気に入りました。



そのため、この本のために別の章を書くことにしました。 私が十分に知っている言語に専念し、その長所と短所を理解しています。これはコトリンです。



この記事の目的は、Kotlin言語を教えることではなく、その特性を示すことです。 彼女を徹底的に理解しようとしないでください。 ここで説明する機能がプログラミングスタイルにどのように影響するかについて、注意を払ってください。



Kotlinの典型的な機能は、この言語が本質的に、他のプログラミング言語でまだ遭遇していないものを導入しないことです。 実際、Kotlinはこれらの古い発見をすべて最も傑出した方法で使用しています。 アイアンマンのスーパーヒーローを思い出してください。 トニー・スタークは、最も単純な電子部品からアイアンマンを組み立てました。 アイアンマンには、スーパーマンやフラッシュのような特徴的な超大国はありません。 これは弱点のように見えるかもしれませんが、長期的にはこれは大きな利点です。 以下でこれについて説明しますが、今のところは基本から始めましょう。







基本



Kotlinは、IDEA IntelliJ、Android StudioまたはCLion(Kotlin / Native)などの1つまたは別のIDEでのプログラミングを目的としています。 ここでは、コマンドラインから始めて、よりシンプルなコンテキストでKotlinをデモンストレーションします。 Kotlinをインストールしたら 、次のようにREPL(インタラクティブシェル)を実行します。







数字を試してみましょう:



>>> 1 1 >>> 1 + 2 3 >>> 1.0 + 2 3.0
      
      





簡単な数学が機能します。 これは、Java仮想マシンで実行されるKotlin / JVMです。 Javaの整数はプリミティブです。 そして、コトリンで? 番号のタイプを確認しましょう:



 >>> 1::class class kotlin.Int >>> 1.0::class class kotlin.Double
      
      





両方ともオブジェクトです! 一般的に、Kotlinではすべてのエンティティはオブジェクトです。 javaはどうですか? KotlinはJavaと完全に相互運用可能ですが、上記の型はKotlin型であることがわかります。 実際、一部のKotlin組み込み型はJava型をカバーしています。 この場合、 Class



java



プロパティまたは任意のオブジェクトのjavaClass



プロパティを使用して、Javaタイプがどのようになるかを確認できます。



 >>> 1.0::class.java double >>> 1.0.javaClass double
      
      





これはdouble



です! Javaの二重数はプリミティブです。 これはどのように可能ですか? Kotlinは、オブジェクト指向機能が使用されていない場合にオブジェクトの代わりにプリミティブを使用できる最適化を採用しています。 これは内部で行われ、開発者にはまったく関係ありません。 オブジェクトとしてdouble



を使用する必要がある場合は、代わりにDouble



が使用されます。 開発者の観点からは、「すべてがオブジェクトである」と言うことができます。 いくつかのプロパティを定義します。



 >>> val a = 1
      
      





このプロパティは読み取り専用です。 var



を使用して読み取りおよび書き込み用のプロパティを定義することもできます。



 >>> var a = 1
      
      





注:タイプはここでは指定されていません。 ただし、これにだまされてはいけません。Kotlinは強力な静的型付けを備えた言語です。 プロパティのタイプは、割り当てられた値のタイプから単純に推測されます。



 >>> ::a.returnType kotlin.Int
      
      





十分な計算ができたら、さらに興味深い機能に移りましょう。



安全性



アイアンマンは、警察も軍隊もテロリストの捕虜からトニー・スタークを救うことができなかったために建設されました。 トニーは、アイアンマンに自分のセキュリティの世話をさせ、能力を拡張しました。 彼もこれで有名になりました。



同様に、JetBrainsはKotlinを作成しました。 同じ会社が最も人気のある統合開発環境を作成しています。 ツールはすべてJavaで作成されていましたが、JetBrainsチームは実際にこの言語のすべての欠陥を感じていました。 その後、ScalaやGroovyなどの他の言語で実験を始めましたが、それらでも満足しませんでした。 したがって、最終的に、JetBrainsは独自の言語を作成し、この新しい言語が最大限のセキュリティ(製品にエラーがないようにする)とスケーラビリティを提供することを目指しました。 さらに、Kotlinの優れたプロピアリルJetBrains。 彼らはすでに世界中で知られていましたが、素晴らしい言語を使用することを決めた専門家のコミュニティが現れたとき、JetBrainsは彼らにとってさらにクールになりました。 (ここで私はこの話を最も一般的な言葉でのみ語った。詳細に興味があるなら、 このポッドキャストを聞いてください)。



Kotlinは、セキュリティの点でJavaを大幅に上回っています。 プロパティを初期化する必要があります。



 >>> var a: String error: property must be initialized or be abstract
      
      





デフォルトでは、型はnull値を許可しません。



 >>> var a: String = null error: null can not be a value of a non-null type String
      
      





この型が無効化されていることを示したい場合、これは?







 >>> var a: String? = null
      
      





確かに、null許容型は明示的に使用できません。



 >>> a.length error: only safe (?.) or non-null asserted (!!.) calls are allowed on a nullable receiver of type String?
      
      





Nullable型は、Scalaで使用されるオプションの型など、他の型と似ています。 使用する前に、このタイプを開梱する必要があります。 プロパティがnull



でない場合、通常の呼び出しと同じように動作する安全な呼び出しを使用できnull



。 プロパティがnull



場合、メソッドは呼び出さず、単にnull



返しnull







 >>> a = null >>> a?.length null >>> a = "AAA" >>> a?.length 3
      
      





プロパティがゼロの場合に例外をスローする安全でない呼び出しを使用することもできます。



 >>> a = null >>> a!!.length kotlin.KotlinNullPointerException
      
      





安全でない呼び出しを処理することは推奨されないため、絶対に必要な場合にのみそれらを使用する必要があります。 Kotlinのプロジェクトでは、それらは非常にまれです。 これは、すべての呼び出しが安全ではないKotlin Javaとの大きな違いです。



知能



アイアンマンはとてもクールです。なぜなら、彼の戦闘スーツは本当に賢いからです。 彼は状況を計算し、トニーに危険について警告します。 Kotlinは真に知的であり、開発者を大いに助けます。



このようなインテリジェンスの一例は、スマートキャスティングです。 プロパティがゼロに等しくないかどうかを確認するときは、実際にゼロでないように使用できます。 より高度な機能を示すために、ファイルを操作します。 IDEA IntelliJを使用することをお勧めします(開始方法についてはここで説明します)。 または、 オンラインREPLでこれらの機能をすべて試すことができます。 例を考えてみましょう:



 fun smartCastingExample(str: String?) { if(str != null) print("Length is " + str.length) }
      
      





ご覧のとおり、strは明示的に使用されます(安全でない呼び出しや安全な呼び出しはありません)。 それが、 if(str != null)



型がString?



からキャストされているString?



をチェックする範囲内にある理由String?



String



。 逆のチェックで関数を終了しても機能します:



 fun smartCastingExample(str: String?) { if(str == null) return print("Length is " + str.length) }
      
      





この原則は、ヌル可能性でのみ機能するわけではありません。 スマートキャストも可能です。



 fun smartCastingExample(any: Any?) { if(any is String) print("String with length " + any.length) }
      
      





KotlinはIDEA IntelliJ、Android StudioまたはCLionで完全にサポートされています。 これらのIDEでは、多くのヒント、トリック、およびサポートが提供されます。 Javaに典型的なコレクションの命令型処理が、Kotlinの特徴的な宣言型のものに置き換えられた例を次に示します。 移行全体を提供および実行するのは開発環境であることに注意してください。







ミニマリズム



トニー・スタークは、彼がそれを必要としない場合、全体としてアイアンマンを着用しません。 通常、彼はマシンまたはいくつかの小さなコンポーネントのみを使用します。







特に、Kotlinの哲学は、単純なものは単純なままでなければならないと仮定しています。 KotlinのHello Worldコードは次のとおりです。



 fun main(args: Array<String>) { print("Hello, World") }
      
      





これは、テキストを表示する関数の1つにすぎません。 他の典型的なKotlin操作も簡単です。 関数全体を必要としないときは、単一​​の式でできます:



 fun add(a: Int, b: Int) = a + b
      
      





以下に、まったく同じミニマリストスタイルが複数回表示されます。



柔軟性



アイアンマンはいくつかの重要な点でスーパーマンに負けています。 たとえば、スーパーマンには誕生からレーザーの目が与えられ、彼は喜んで敵を目で焼却することができます。 トニー・スタークはアイアンマンにアイレーザーを装備していませんでした-おそらく彼がこれを緊急の必要性として見なかったからです。 ここで、彼がIron Manにそのような機能を簡単に追加できることに注意することが重要です。 実際、これはIron Manのユーザーの力の範囲内です。 しかし、同時に、他のアップグレードもIron Manに掛けることができます。これは、それほど効果的ではないかもしれませんが、より安くなります。 これは柔軟性の大きな可能性です。 練習に移りましょう。 ほとんどのプログラミング言語は、何らかの方法でコレクションリテラルを提供します。 Python、Ruby、またはHaskellでは、リストは[1,2,3]



ように定義できます。 Kotlinにはそのようなコレクションリテラルはありませんが、トップレベル関数(どこでも使用できるもの)を提供し、Kotlin標準ライブラリにはコレクションを作成できるトップレベル関数があります。



 >>> listOf(1,2,3) [1, 2, 3] >>> setOf(1,2,3) [1, 2, 3] >>> mapOf(1 to "A", 2 to "B", 3 to "C") {1=A, 2=B, 3=C}
      
      





なぜこれがそんなに重要なのですか? コレクションリテラルが言語で提供される場合、ユーザーがコレクションを使用する方法も決定します。 すべてのコレクションにはいくつかの特徴があります。 どのリストがより良いか-可変であるか不変であるかについて、広範な議論がありますか? 変数はより効率的ですが、不変ははるかにスレッドセーフです。 このテーマについては多くの意見と議論があります。 これを念頭に置いて、リストリテラルで可変リストまたは不変リストを生成しますか? いずれにせよ、プログラマーはコレクションリテラルを使用することを好むため、言語を使用するためのプログラマーオプションを何らかの形で課すことになります。 この場合、Kotlinは選択の自由を残します。 listOf



setOf



およびlistOf



、不変のコレクションを提供します。



 >>> var list = listOf(1,2,3) >>> list.add(4) error: unresolved reference: add list.add(4) ^ >>> list + 4 [1, 2, 3, 4]
      
      





mutableListOf



mutableSetOf



およびmutableMapOf



を使用して可変コレクションを作成することは難しくありませんが、



 >>> mutableListOf(1,2,3) [1, 2, 3] >>> mutableSetOf(1,2,3) [1, 2, 3] >>> mutableMapOf(1 to "A", 2 to "B", 3 to "C") {1=A, 2=B, 3=C}
      
      





注:誰でも独自のコレクションを定義し、それを作成するトップレベル関数を定義できます。



 fun <T> specialListOf(vararg a: T): SpecialList<T> { //  }
      
      





上記で、 T



型の一般化されたパラメーターを使用したことが簡単にわかりますT



心配しないで。 つまり、このタイプのコレクションを作成するには、同じタイプの要素のセットを渡す必要があります。



Kotlinは組み込みリテラルではなく基本機能を使用しているため、Kotlinを使用するサードパーティライブラリは標準ライブラリよりも強度が劣っていません。 ライブラリを大幅に民主化し、開発者の手を解放するもう1つの優れた機能は、いわゆる拡張機能です。 要するに、メソッドとして機能するように関数を定義できます。



 >>> fun Int.double() = this * 2 >>> 2.double() 4
      
      





注:実際には、クラスにメソッドは追加されません。 拡張関数は、この特別な方法で呼び出される単なる関数です。 この機能は単純に見えるかもしれませんが、本当に強力です。 たとえば、Kotlinは、他の現代言語と同様に、コレクションを処理するための機能を提供します。



 class Person(val name: String, val surname: String) val avengers = listOf( Person("Tony", "Stark"), Person("Steve", "Rogers"), Person("Bruce", "Banner"), Person("Thor", "") ) val list = avengers .filter { it.surname.isNotBlank() } .sortedWith(compareBy({ it.surname }, { it.name })) .joinToString { "${it.name} ${it.surname}" } print(list) // :  ,  ,  
      
      





Kotlinの大きな利点は、そのような関数と同様の関数が拡張関数として定義されていることです。 たとえば、 filter



実装を見てください。



 inline fun <T> Iterable<T>.filter( predicate: (T) -> Boolean ): List<T> { return filterTo(ArrayList<T>(), predicate) } inline fun <T, C : MutableCollection<in T>> Iterable<T>.filterTo( destination: C, predicate: (T) -> Boolean ): C { for (element in this) if (predicate(element)) destination.add(element) return destination }
      
      





実装する価値がない場合は、この関数を自分で定義できます。 コレクションを処理するために他の関数が必要な場合は、簡単に定義できます。 開発者はしばしばこれを行います。 たとえば、Androidの拡張機能を定義する多くのライブラリを見つけることができます。 Androidの開発を簡素化します。 この決定の別の結果-あなたのサービスには、コレクションを処理するための多くの方法があります。



ここで、 filter



List



型ではなくIterable



インターフェイスを拡張する関数であることに注意することも重要です。



 public interface Iterable<out T> { public operator fun iterator(): Iterator<T> }
      
      





Iterable



を実装するコレクションクラスを簡単に定義できます。コレクション言語を使用すると、コレクションを処理するためのこれらのメソッドを追加できます。 String



でも実装されています。 String



を使用してコレクションを処理するすべての方法を使用できる理由は次のとおりです。



 >>> "I like cake!".map { it.toLowerCase() }.filter { it in 'a'..'z' }.joinToString(separator = "") ilikecake
      
      









簡単な要約



トニー・スタークはスーパーヒーローとして生まれたわけではなく、放射性スパイダーも彼に噛みつきませんでした。 彼は信じられないほどの知識と経験のおかげでアイアンマンを設計しました。 同様に、JetBrainsは、さまざまな言語用の優れたIDEを作成する会社です。 彼女の人々はこの仕事から多くを学び、信じられないほどのプログラミング言語を書くことによって彼らの知識を具体化しました。 彼らはプログラミングの世界に新しいものをもたらすことはしませんでしたが、他の多くのプログラミング言語の利点を活用する完璧に完成した言語を提供しました。したがって、開発者の生産性と最高品質のプロジェクトを最大化します。



このようなスマートなデザインの素晴らしい例は、Kotlinタプルです。 言語がまだベータ版で存在したとき、それはすでにタプルをサポートしていました。 しかし、Kotlinチームがタプルの操作がプログラムの開発にどのように影響するかを正確に分析したとき、それらの影響が常にプラスになるとは限らないことが判明しました。 タプルがリリースに含まれていなかったのはそのためです。 代わりに、Kotlinでdata



注釈を使用できます。 それはより普遍的であり、Kotlin開発者は、一般に、言語での作業にプラスの影響を与えることは間違いありませんでした。 タプルはまだ議論されており、おそらくいつかKotlinはそれらのネイティブサポートを取得するでしょう。 ただし、これを実現するには、Kotlinチームと開発コミュニティが、そのようなソリューションが実現可能であることを確認する必要があります。



これはコトリンを雄弁に特徴づけています。 これはアイデアの寄せ集めではなく、本当によくできた言語です。 これには、最も強力な機能の最小限のセットが含まれており、合計ですばらしい機会を提供します。 一般に、Kotlinは共同作成を含め、より多くの自由を与えます。



ホームリーディング



Kotlinをより詳細に理解したい場合は、 言語のドキュメントを読むことと、 Kotlin Koansリソースに精通することをお勧めします。 Android向けKotlinに興味がある場合は、 この本をご覧ください。



All Articles