Kotlin

メインページ > 工学 > 情報技術 > プログラミング > Kotlin
Kotlinは、JetBrains社によって開発された静的型付けされたオブジェクト指向のプログラミング言語で、Java仮想マシン(JVM)上で動作します。JavaScriptや、LLVMフレームワークを介して多くのプラットフォームで実行可能なコードにもコンパイルできます。 また、Kotlin/Wasmは、Kotlinの新しいコンパイルターゲットであり、WebAssemblyをサポートする環境やデバイス上で実行可能なアプリケーションを作成することができます。これにより、Kotlinの強力な機能と柔軟性を活用して、Webアプリケーションやクライアントサイドのプログラミングにも取り組むことができます。
KotlinはJavaよりも簡潔で型安全性が高く、Scalaよりもシンプルな言語を目指して開発されました。Scalaと比較して、簡略化された結果、コンパイルが高速化され、IDEでの言語サポートも充実しています。また、KotlinはJavaと完全な互換性があり、Java開発者は徐々に導入することができます。特に、KotlinはAndroidにも組み込まれており、既存のAndroidアプリケーションは、アプリケーション全体を書き換えることなくKotlinで新機能を実装することができます。Kotlin FoundationがKotlinTM商標を守っています。

Kotlinは多様なプラットフォームで利用できるモダンで柔軟なプログラミング言語です。
このチュートリアルに取り組む前に、以下の予備知識が役立ちます。
以上の予備知識を持っていると、Kotlinをより効果的に学習し、異なるプラットフォームでの利用に対応することができます。各プラットフォームにおけるKotlinの特徴や最適な利用法を理解することで、幅広い開発環境で柔軟かつ効率的なプログラミングが可能になります。
Kotlinを学ぶ際に他の言語のプログラミング経験がある場合、以下のアドバイスが役立つかもしれません。
総じて、Kotlinは他のプログラミング言語において得た経験を活かしやすい言語です。適応期間は短く、生産性を高めるために積極的に新しい機能や手法を試してみることが重要です。また、公式のドキュメントやサンプルコードを利用して、Kotlinの言語仕様やベストプラクティスに精通することもおすすめです。
プログラミング未経験者がKotlinやプログラミング全般に取り組む際のアドバイスは以下の通りです:
プログラミングは絶え間ない学習が求められる分野です。新しい技術やツールに興味を持ち、継続的に学び続けることでスキルを向上させることができます。
プログラミングはスキルの向上に時間がかかるものですが、継続的な努力と実践を通じて着実に成長していきます。最初は小さなステップから始め、徐々に進んでいくことが大切です。
他の多くのチュートリアルがそうであるように、 私たちもまずはKotlinの世界にあいさつすることから始めましょう。hello.ktというファイルを作り、次のように書いて保存して下さい(Kotlinのソースファイルの拡張子は .kt です)。
それでは、ソースプログラムをコンパイルして実行してみましょう。
これにより、この一行のコードは「mainという関数を宣言し、その中で 'Hello, World!' という文字列をコンソールに表示する」という単純なプログラムを実現しています。Kotlinはこのようにシンプルかつ読みやすい構文を持っており、初学者にも優れた学習言語となっています。

Kotlinのクイックツアーでは、基本的な構文や機能に焦点を当て、簡単なコード例を通じて言語の特徴を理解していきます。
この例では、Kotlin DSLを使用して、特定のドメイン(ここではPersonオブジェクトの構築)に特化した言語拡張を行っています。
これらの例はKotlinの基本を紹介するものであり、より高度な概念や機能も学ぶことができます。
Kotlinは、ターゲットごとに
の3つの実装があり、ツールチェインとしては統合されていますが、使用するコマンドやオプションが異なります。
Kotlin/JVM 環境をインストールする手順は以下の通りです:
以上で、Kotlin/JVM 環境のインストールが完了します。
Kotlin/JVM では、Kotlin のソースファイルからJARファイルをコンパイルします。 Kotlin のソースファイルの拡張子は .kt です。
hello.kt をコンパイルして hello.jar を得るのであれば
生成された hello.jar を実行するには
別のKotlinのソースファイル universe.kt をコンパイル/実行するには hello を filename に読替えて同じ手順を行えばいいのですが、このような単純作業はコンピューターに任せましょう。
ビルド手順の自動化を行うツールに make があります。 make にはいくつかの方言がありますが、BSD-make と GNU-make に共通した構文を紹介します。
コマンドラインでの操作は
この様に、make を使うとファイルのタイムスタンプから必要な処理を判断し実行します。
make と同じくビルドツールに gradle があり、gradle のビルドルールは Kotlin Script で書けるので、Kolin の学習には gradle が適しているとも言えますが、ビルドルールを書くためにKotlinのコードを読み書きする必要があるという「鶏卵問題」に陥るので、より一般的な make を紹介しました。
ここでは、kotlinソースからJARファイルをコンパイルし実行する最小限のルールを書きましたが、機会をみて、make のチュートリアルを書こうと思います。
エラトステネスの篩を、若干 Kotlin らしく書いてみました。
最大公約数と最小公倍数を、若干 Kotlin らしく書いてみました。
それぞれの関数定義は式形式で1行なので拍子抜けですが、概念を簡素にかけていると思います。
二分法を、若干 Kotlin らしく書いてみました。
オーソドックスな複素数型の実装(Kotlinの標準ライブラリーには複素数型が見当たらなかったので)
KotlinとJavaは、どちらもJava Virtual Machine(JVM)上で動作するプログラミング言語です。以下は、KotlinとJavaの主な比較ポイントです。
総合的に見ると、KotlinはJavaよりも簡潔で読みやすく、より現代的な言語機能を備えています。ただし、Javaのライブラリやフレームワークを使用する場合は、Javaを使用することが必要な場合があります。
KotlinとScalaは、どちらもJVM(Java Virtual Machine)上で動作する静的型付け言語であり、それぞれ異なる特徴を持っています。以下に、KotlinとScalaをいくつかの側面で比較してみます。
総合的に見ると、KotlinはJavaからの移行が容易であり、Androidアプリケーションの開発に特に適しています。一方で、Scalaは関数型プログラミングの特徴を生かして複雑なシステムの開発に向いており、高度な拡張性を提供しています。選択する言語は、開発の目的や開発者のスキルセットによって異なることがあります。
KotlinとSwiftは、それぞれAndroidとiOSのアプリ開発で主に使用されるプログラミング言語です。以下に、両言語の類似点と相違点をいくつか挙げてみます。
どちらの言語も優れた特性を持っており、選択はプロジェクトのニーズや開発者の好みによって異なります。
Kotlinでは、関数 mainがエントリーポイントです。
なにもしないプログラムはこの様になります。
パッケージの指定は、ソースファイルの冒頭(shebang!の次)で行ってください。
ディレクトリとパッケージの一致は必須ではなく、ソースファイルはファイルシステム上に任意に配置することができます。
Kotlinでは、特定のパッケージやクラスを明示的にインポートすることなく、いくつかのデフォルトのインポートが提供されています。これにより、コードをより簡潔にし、冗長性を減少させることができます。以下は、デフォルトでインポートされる主要なパッケージです。
また、ターゲットプラットフォームに応じて、追加のデフォルトインポートが行われます。
上記のパッケージは、明示的にインポートすることなく既にインポートされています。
このようなデフォルトのインポートにより、開発者は冗長なコードを書かずに済み、効率的にKotlinの機能を利用することができます。
以下は、デフォルトでインポートされる主要なパッケージの概要を表形式でまとめたものです。
また、ターゲットプラットフォームによっては、追加のデフォルトインポートが行われます。
これらのデフォルトインポートは、通常のKotlinプロジェクトで基本的な操作や機能を利用するための便利な手段となります。
デフォルトインポートとは別に、各ファイルは独自の import ディレクティブを含むことができます。
単一の名前でインポートすることができます。
または、パッケージ、クラス、オブジェクトなどのスコープのすべてのアクセス可能なコンテンツをインポートすることができます。
名前の衝突がある場合、as キーワードを使用して、衝突するエンティティの名前をローカルに変更することで、曖昧さをなくすことができます。
import キーワードは、クラスのインポートに限定されません。他の宣言をインポートするためにも使用することができます。
トップレベル宣言が private とマークされている場合、その宣言が行われたファイルに対してプライベートとなります。
いかなる関数スコープにも属さないオブジェクトのことを、トップレベルオブジェクト( top level object )と言います。
Kotlinには、行末で終わるコメントと、複数行に渡ることと、入れ子にすることができるコメントがあります。
Kotlinでは、任意のインスタンスに対してプロパティーを参照したりメンバー関数を呼出すことができるという意味で、すべてのインスタンスがクラスに属しています。 いくつかの型は特別な内部表現を持つことができます。例えば、数字、文字、ブール値は実行時にプリミティブ値として表現できますが、ユーザーからは参照されるときに自動的にボックス化されるので普通のクラスのインスタンスのように見えます。 これらの型は基本的にJavaのプリミティブに一対一に対応しますが、Stringだけはjava.lang.Stringクラスに対応しています。 基本型は Package kotlin で定義されています。
Kotlinの論理型は Boolean で
の2つの値以外は取りえません。
JVMでは、この型の非Nullable値は、プリミティブ型のbooleanの値として表現されます。 論理型と数値型は可換ではないので、制御構造の条件式などでもゼロとの比較を行う必要があります。
Kotlinの数値型は、整数型と浮動小数点数型に分かれています。 これらの型は、抽象クラスである Number クラスから派生しており、具象クラスとして利用されます。
なお、文字型は数値型と可換ではありません。
Kotlinの整数型には、符号付き整数型と符号なし整数型があります。 符号なし整数型の名前は、対応する符号付き整数型の名前の先頭に U を補ったものになります。以下が主な整数型です:
Kotlinの浮動小数点数型には、以下の2つがあります:
これらの数値型は、数学的な演算や精密な計算に利用され、Kotlin言語において数値処理をサポートする基本的な要素となっています。
Charクラスは文字を表すクラスです。'a' のようなKotlinプログラム内の文字リテラルはすべてこのクラスのインスタンスとして実装されています。 Charは、16ビットのUnicode文字を表します。これは、Charがすべての文字をユニコード文字を表すことが出来ない事をしめしています。
Kotlinは、Javaの文字エンコーディングシステムを引継いだので、Charの収まらない文字の問題に限らずUnicodeを内部エンコーディングに使っていることに起因する厄介ごとと付き合い続ければなりません。
Charでは、いくつかの演算子が定義されています。
特殊文字は、エスケープする \(バックスラッシュ)から始まります。以下のエスケープシーケンスに対応しています。
その他の文字をエンコードする場合は、Unicodeエスケープシーケンス構文を使用します。'\uFF00' を使用します。
String クラスは文字列を表すクラスです。"abc" のようなKotlinプログラム内の文字列リテラルはすべてこのクラスのインスタンスとして実装されています。 Kotlinでは、文字列( String )と文字( Char )とは直接の関係はありません(StringはCharの配列ではありません)。
Stringでは、加算演算子を連結として定義されています。
加算演算子( + )は、文字列( this )と与えられた他のオブジェクトの文字列表現を連結して得られる文字列を返します。
既に紹介したように、Stringクラスのリテラルは "(ダブルクオーテーション)で括った文字列です。
Stringリテラルには変数や式を埋込むことが出来ます。 このように、変数や式が埋込まれたStringリテラルのことをテンプレートリテラルといいます。
生文字列( Raw strings )は、改行や任意のテキストを含むことができます。トリプルクォート(”””; triple quote )で区切られ、エスケープを含まず、改行や他の任意の文字を含むことができます。
Kotlinで配列型は Array で、main() の引数でも使われています。
Array(), arrayOf(), arrayOfNulls() や emptyArray() で生成します。
Kotlinには、IntArray、DoubleArray、BooleanArray、CharArrayなどのプリミティブ型を要素とする配列のクラスが用意されています。 これらを総称してプリミティブ型配列( Primitive type arrays )と呼びます。 プリミティブ型配列は、機能的にはArray<T>のTにプリミティブ型を与えたものと変わりありませんが、ボックス化されないので性能向上とフットプリントの削減が期待できます。 このため、プリミティブ型配列はArrayを継承していません。
StringArray はありません。
基本型の他にも幾つかの特別な型があります。 これらは、基本型同様 Package kotlin で定義されています。
AnyはKotlinのクラス階層のルートです。すべてのKotlinクラスはAnyをスーパークラスとして持っています。 クラス定義で継承元を指定しないと Any が暗黙の継承元になります。 また、Anyクラスのオブジェクトは、あらゆるオブジェクトを代入できます。
Unitは、何も返さない関数の戻値の型です。JVMでは、Javaのvoid型に相当します。
は
と等価です。
Nothingはインスタンスを持ちません。例えば、ある関数の戻り値がNothingであれば、それは決して戻らない(常に例外を投げる)ことを意味します。
KotlinのNULL安全性(Null safety)とNullableに関して、以下のポイントが重要です。
KotlinのNull安全性とNullable型は、プログラミングにおける安全性と信頼性を向上させるための重要な機能です。これらの機能を適切に理解し、利用することで、Nullによるエラーを最小限に抑えることができます。
Javaを含む多くのプログラミング言語における最も一般的な落とし穴の1つは、Null参照のメンバーにアクセスするとNull参照例外が発生することです。Javaでは、これはNullPointerException、略してNPEと呼ばれるものに相当します。
KotlinでNPEが発生する原因として考えられるのは、以下の通りです。
Kotlinの型システムでは、nullを保持できる参照(Null可能参照; nullable references )とそうでない参照(非Null参照; non-null references )を区別しています。例えば、String型の通常の変数はnullを保持できません。
nullを許容するには、String?と書いて変数をnull可能な文字列として宣言します。
さて、aのメンバー関数を呼び出したり、プロパティーにアクセスしたりしても、NPEが発生しないことが保証されています。
しかし、bのメンバー関数を呼び出したり、プロパティーにアクセスしたりすると、それは安全ではなく、コンパイラはエラーを報告します。
それでもそのプロパティにアクセスする必要がありますよね?そのためには、いくつかの方法があります。
まず、bがnullかどうかを明示的にチェックし、2つの選択肢を別々に処理することができます。
コンパイラーは実行したチェックの情報を記録し、ifの内部でlengthの呼出しを可能にする。より複雑な条件もサポートされています。
註:b が immutable な場合 (つまり、チェックから使用までの間に変更されないローカル変数か、 バッキングフィールドを持つオーバーライド不可のメンバー変数) にのみ有効です。
Not-Null断定演算子(!!)で任意の値をnullでない型に変換し、値がnullの場合は例外をスローします。b!!と書くと、bの非null値(例えばこの例ではString)を返し、bがnullの場合はNPEを投げます。
このように、NPEを発生させたい場合は、明示的に要求する必要があり、突然発生することはありません。
?. 演算子は、null安全性を保証しつつ、str 変数がnullでない場合に length プロパティにアクセスします。str がnullの場合、length には null が代入されます。
このように、?. 演算子はnull値を安全に処理するために使用されます。例えば、Javaの場合、nullチェックを行わないとNullPointerExceptionが発生しますが、Kotlinでは ?. 演算子を使用することで、nullに対する操作を安全に行うことができます。
変数の名前のような名前を識別子( identifiers )と呼びます。 変数ほかに、関数、クラス、クラスのメンバー、クラスのメンバー関数、enum、ラベルなどの名前も識別子です。
Kotlinでは、変数は使う前にかならず宣言する必要があります。
いままでの例で既に型推論( type inference ) は使われています。 変数を宣言するときに、特に型を明示しませんでしたが、初期化式の型から変数の型を特定していたのです。
初期化式は省略可能です。 その場合は変数の型がわからないので型アノテーション( type annotation )が必要になります。
シャドーイング( Shadowing )とは、スコープ内の2つの宣言が同じ名前になり、より内側の識別子が外側の識別子を隠すことです。
多くのシャドーイングは無害ですが...
オブジェクトを複数の変数に分解して初期化する宣言する方法があり、分解宣言( Destructuring declarations )と呼ばれます。
Kotlinでは、演算子はメソッド形式の別名を持ちます。 例えば、a + b は a.plus(b) とも書けます。 この plus メンバー関数を再定義すると、演算子オーバーロードができます。
演算子は、もちろん加算だけではありません。

Kotlinは、if と when の2つの分岐構文を持ち、両方とも値を返す式です。
if式は、条件式に基づき分岐し、分岐先の式を評価します。 if式の値は、分岐先の式の値です(C言語系の三項演算子に相当する働きをします)。 if式の値を右辺値化した場合、else節は必須です。
if や while の条件式は
でなければいけません。
when式を使って条件分岐をすることができます。 when 式は、when に与えられた式(境界値)に最初にマッチするパターンに結びついた値を返すパターンマッチングです。 式が省略されると、パターンの条件が最初に真になるパターンに結びついた値を返します。
whenは式なので以下のように書換えることができます。
区切子 -> を使った構文の左辺の条件には、以下のようなバリエーションがあります。
when 文は、多くの条件分岐をシンプルに表現するための強力な構造です。境界値が省略された場合、true が境界値とみなされます。
when 文を使うことで、このような条件分岐をより簡潔に表現できます。
境界値を省略した例として、以下のコードを見てみましょう。
このコードでは、when 文が x の値に基づいて文字列を返します。境界値が省略されているため、条件が true のブロックが実行されます。
when 文を使用してループから脱出する例もあります。以下は、when 文を使って特定の条件でループを脱出する例です。
このコードでは、when 文を使用して number が3の場合にループから脱出します。
enum クラスを使った when 文の例も挙げてみましょう。
このコードでは、enum クラス Day を使用して、曜日に応じた活動を選択しています。when 文が enum の各ケースを処理し、対応する活動が選択されます。
Kotlinには、while・do-while と for の3つの繰返し構文があります。これらは文で、値を返すことはできません。
whileは、条件式が true の間、式を評価しつづけます。
do-whileは、条件式が true の間、式を評価しつづけるという意味では、whileと同じですが、条件式がループの最後にある、つまり条件が成立しなくても1周はループが回ることが異なります。
Kotlinのforはw:foreach文タイプのループ構文で、C言語の for(;;) とは異なる構文です。
関数は、キーワード fun を使って定義します。
関数のボディが単一の式からなる場合、{ return 式 } を、= 式と書くことができます。
初見だと驚きますが、関数型プログラミング風の書き方が簡素にできます。 特に、ifやwhenが値を返すことができる式であることが効いてきます。
ボディが単一の式からなる関数定義では、戻値式の型が推論できる場合が多いので、戻値型を省略できる場合があります。
再帰関数の戻値型を省略しようとすると、自分自身が型不明な項になりコンパイルできません。
関数の引数はイミュータブルです。 これは Zig も同じで、新興言語は不用意な書換えによる古参言語で度々アクシデントのもととなった引数の破壊を永久になくしたいようです。
関数には、引数にディフォルト値を設定できます。これにより、呼び出し側は引数を指定しなくても関数を呼び出すことができます。
たとえば、次の関数は、名前と年齢の2つの引数を取ります。名前には「John Doe」というデフォルト値が設定されています。
この関数を呼び出すには、名前を指定するか、デフォルト値を使用できます。
関数の引数にデフォルト値を設定すると、呼び出し側がすべての引数を指定する手間を省くことができます。また、関数の使い方を覚えやすくすることもできます。
次のコードは、関数指向の構文を使用して関数を呼び出す方法を示しています。
このコードは、add 関数を呼び出して、2つの引数 1 と 2 を渡します。add 関数は、これらの引数を受け取った後、それらを加算して結果を返します。関数 main は、結果をコンソールに出力します。
次のコードは、メソッド指向の構文を使用して関数を呼び出す方法を示しています。
このコードは、Person クラスのインスタンスを作成し、name プロパティに John Doe という値、age プロパティに 30 という値を設定します。次に、greet メソッドを呼び出して、インスタンスの名前を出力します。
Kotlin は関数を呼出す時、引数を名前で指定する事ができます。
関数修飾子 infix を使うと、中置表現の関数呼出しを行うことができるようになります。外観は文法を拡張したかのような印象をうけます。
関数スコープは、変数や関数が定義され、利用可能な範囲を指します。Kotlinでは、関数スコープ内で定義された変数や関数はそのスコープ内でのみアクセス可能で、外部のスコープからは見えません。
以下に、関数スコープの基本的な特徴と例を示します。
この例では、main 関数が外部のスコープで、myFunction が関数スコープ内で宣言されています。main 関数内では outerVariable にアクセスでき、myFunction 内では innerVariable と innerFunction にアクセスできます。ただし、逆は成り立ちません。
関数スコープは、変数や関数の可視性を制御し、プログラムの構造を整理する上で重要な役割を果たします。関数ごとにスコープが分離されるため、変数や関数の名前の衝突を防ぎ、コードの保守性を向上させます。
可変長引数( Variable-Length Arguments )は、関数が異なる数の引数を受け入れることを可能にする Kotlin の機能です。これは vararg キーワードとスプレッド演算子( spread operator )を使用して実現されます。
このように、関数を呼び出す際に異なる数の引数を渡すことができます。可変長引数は、同じ型の引数が複数個ある場面で便利です。
スプレッド演算子( Spread Operator )は、リストや配列などの要素を展開して、可変長引数として渡すための演算子です。
この例では、arrayOf で作成した配列の要素をスプレッド演算子 * を使って myVaPrint 関数に渡しています。これにより、配列の各要素が可変長引数として関数に渡されます。
可変長引数とスプレッド演算子の組み合わせにより、異なる数の引数を柔軟に扱うことができ、関数の再利用性を向上させます。
引数あるいは戻値あるいは両方が関数の関数を高階関数()と呼びます。
ラムダ式( lambda expressions )では、波括弧の周囲と、パラメータと本体を分ける矢印の周囲に空白を使用する必要があります。ラムダを1つだけ指定する場合は、可能な限り括弧で囲んでください。
また、ラムダのラベルを指定する場合、ラベルと中括弧の間にスペースを入れてはいけません。
上記のラムダ式構文には、関数の戻値の型を指定する機能がひとつだけ欠けています。ほとんどの場合、戻値の型は自動的に推測されるため、この指定は不要です。しかし、明示的に指定する必要がある場合は、別の構文として無名関数( Anonymous functions )を使用することができます。
ラムダ式や無名関数(ローカル関数やオブジェクト式も同様)は、外部スコープで宣言された変数を含むクロージャー( Closures )にアクセスすることができます。クロージャーに取り込まれた変数は、ラムダ式で変更することができます。
高階関数を使用すると、ある種の実行時ペナルティーが課せられます。各関数はオブジェクトであり、クロージャーを捕捉します。クロージャー( closure )とは、関数本体でアクセス可能な変数のスコープです。メモリー確保(関数オブジェクトとクラスの両方)と仮想呼出しは、実行時オーバーヘッドを発生させます。
しかし、多くの場合、ラムダ式をインライン化することで、この種のオーバーヘッドをなくすことができます。
Kotlin は、特に修飾辞なしに関数を再帰呼び出しできます。
tailrec は、Kotlinのキーワードで、末尾再帰最適化(Tail Recursion Optimization)を実現するために使用されます。末尾再帰最適化は、再帰関数が最後の操作として再帰呼び出しを行う場合に、スタックの消費を減少させる最適化手法です。これにより、スタックオーバーフローを避けることができます。
上記の例では、factorial 関数が末尾再帰関数として宣言されています。再帰呼び出しは末尾で行われており、コンパイラが最適化を行うことが期待されます。
tailrec を使用するためにはいくつかの制約があります。
tailrec を使うと、再帰関数の性能を向上させることができます。ただし、制約を理解し、満たすことが重要です。tailrec が適用される場合、コンパイラはループに変換し、スタックの使用を最小限に抑えます。
Kotlinでは、クラスやインターフェースを継承したり、Decoratorのようなデザインパターンを使わずに、新しい機能を拡張することができます。これは、拡張( extensions )と呼ばれる特別な宣言によって実現されます。
拡張関数( Extension functions )を宣言するには、その名前の前に拡張される型を示すレシーバー型をつけます。以下は、Array<Int>にrotate関数を追加したものです。
拡張関数でもジェネリックス(型パラメーター)が使用可能です。
先の例は、Array<Int>とIntのアレイ専用でしたが、任意の型 T のアレイ Array<T> に拡張関数を拡張してみましょう。
拡張は、一見するとクラスの中に後からメンバー関数を追加しているように見えるかもしれませんが、インスタンス.メソッド(実引数リスト) のパターンに合致する拡張定義があるかを静的に調べ、該当する拡張関数があればそれを呼出すことで実現しています。
このため拡張関数でメンバー関数をオーバーライドすることはできません。
Kotlinは関数型プログラミング言語であると同時に、クラスベースのオブジェクト指向プログラミング言語です。 クラス( class )はオブジェクトの設計図であり、インスタンスはその設計図に基づいて作成されます。
クラスは、キーワード classを使って定義します。
Kotlinのクラスはプライマリーコンストラクターと1つまたは複数のセカンダリーコンストラクターを持つことができます。プライマリーコンストラクターはクラスヘッダの一部で、クラス名とオプションの型パラメターの後に続きます。
メンバー関数は、クラス定義の中で定義された関数です。 メンバー関数の呼出はドット記法で行います。 メンバー関数からは、プライベートなクラスのメンバーにアクセスできます。
オブジェクトは、匿名クラスの定義とインスタンス化を同時に行うものです。
クラスは、明示的に継承元を指定しない場合は Any を継承します。
継承モディファイア( inheritance modifier )には、次のような種類があり、これらのトークンはモディファイア・キーワードです。
抽象クラス( abstract class )は、抽象メンバー関数( abstract method )だけを持つクラスです。 モディファイア・キーワード abstract は、抽象メンバー関数の定義でも使われます。
ファイナルクラス( final class )は、継承を禁止したクラスです。 KotlinのクラスはJavaと異なり、ディフォルトで継承禁止なので、継承禁止を強調する意味しかありません。 モディファイア・キーワード final は、オーバーライド禁止メンバーの宣言でも使われます。
オープンクラス( open class )は、継承を許可したクラスです。 KotlinのクラスはJavaと異なり、ディフォルトで継承禁止なので、継承を行う可能性がある場合は明示的に許可する必要があります。 モディファイア・キーワード open は、メンバー関数のオーバーライド許可でも使われます。
クラスのメンバー関数が、プロパティやメンバー関数を参照するとき、クラスの外の変数や関数との間で曖昧さが生じる事があります。 このようなときには、インスタンスを表すキーワード this を使います。
this はこのほか、2 次コンストラクタから同じクラスの別のコンストラクタを呼出すときにもつかわれます。
クラスモディファイア( class modifier )には、次のような種類があり、これらのトークンはモディファイア・キーワードです。
列挙型クラス( Enum class )は、有限個の識別子の集合を表現するために使用されます。
シールドクラス( Sealed class )は、制限されたクラス階層を表現するために使用されます。
アノテーションクラス( annotation class )は、コードにメタデータを付加するための手段を提供します。
データークラス( Data class )は、データーを保持するためのクラスで、copy() などのメンバー関数がクラスを定義しただけで生えてきます。
インナークラス( Inner class )は、入れ子になった内側になったクラスが外側のクラスのメンバーにアクセスすることを可能にします。
値クラス( Value class )は、イミュータブルなスカラー値の型を定義します。プロポーザル段階では inline class と呼ばれていました。
+ ラッパークラスとして機能し、型安全性やコードの表現力を向上させます。
オブジェクト( object )は、モディファイア・キーワードではありませんが、特殊なクラスの一種なので併せて紹介します。 オブジェクトは一過的な匿名クラスを定義し、そのインスタンスの生成を行います。
各クラスモディファイアは、異なる用途や特性を持っており、柔軟なクラス定義を可能にします。 適切なモディファイアを選択することで、コードの意図を明確に表現し、保守性や可読性を向上させることができます。
クラス、オブジェクト、インターフェース、コンストラクター、関数、およびプロパティとそのセッターは、可視性モディファイア( Visibility modifiers )を持つことができます。ゲッターは常にそのプロパティと同じ可視性を持っています。
可視性モディファイアには、次のような4種類があり、これらのトークンはモディファイア・キーワードです。
デフォルトの可視性はpublicです。
関数、プロパティ、クラス、オブジェクト、およびインタフェースは、パッケージの中で直接「トップレベル」で宣言することができます。
クラス内部で宣言されたメンバー。
protectedまたはinternalメンバーをオーバーライド( override )し、可視性を明示的に指定しない場合、オーバーライドしたメンバーも元のメンバーと同じ可視性を持つことになります。
クラスの一次コンストラクタの可視性を指定するには、次の構文を使用します。
ローカル変数、関数、クラスは可視性モディファイアを持つことができません。
internal 可視性モディファイアは、そのメンバーが同じモジュール内で可視であることを意味します。具体的にモジュールとは、例えば、一緒にコンパイルされたKotlinファイルの集合のことです。
抽象クラス( abstract class )は、抽象メソッド( abstract method )だけを持つクラスであり、直接のインスタンス化ができません。抽象メソッドは本体を持たず、具体的な実装はそのサブクラスに委ねられます。Kotlinでは、abstract キーワードを使用して抽象クラスと抽象メソッドを宣言します。
上記の例では、Shape という抽象クラスがあります。このクラスは抽象メソッド draw を宣言しています。サブクラスである Circle と Rectangle は、それぞれ draw メソッドをオーバーライドして具体的な実装を提供します。
抽象クラスは直接インスタンス化できないため、Shape クラスのインスタンスを作成しようとするとコンパイルエラーが発生します。代わりに、具象サブクラスである Circle や Rectangle のインスタンスを作成して使用します。
抽象クラスは抽象プロパティを持つこともできます。また、抽象クラス自体はコンストラクタを持つことができます。
この例では、Shape クラスはコンストラクタを持ち、name という抽象プロパティを宣言しています。サブクラスである Circle と Rectangle は、コンストラクタで name を渡し、draw メソッドをオーバーライドしています。
抽象クラスは、クラス階層の一部として柔軟で再利用可能なコードを設計する際に役立ちます。
抽象クラスは、以下のようなユースケースやベストプラクティスに適しています。
抽象クラスは、柔軟性と再利用性を向上させるために使われますが、適切に設計される必要があります。必要以上に多くの機能を含めると、過度な依存関係が生まれる可能性があるため、慎重な設計が求められます。




ファイナルクラス(final class)は、Kotlinにおいて継承を禁止したクラスを指します。Kotlinでは、デフォルトでクラスが継承不可(final)となっており、継承可能にするためには明示的にopen修飾子を使用する必要があります。そのため、finalキーワードは主にオーバーライド禁止メンバーの宣言で使用され、クラス自体に適用することは少ないです。
上記の例では、MyFinalClass はファイナルクラスとして宣言されています。このクラスは他のクラスから継承できません。
上記の例では、MyBaseClass の myFinalMethod は final 修飾子が付いており、このメソッドはオーバーライドできません。
上記の例では、Configuration クラスがファイナルクラスとして定義されています。このクラスは他のクラスから継承できないため、設定情報の不正な変更や上書きを防ぐことが期待されます。ApplicationSettings クラスは Configuration を利用してアプリケーションの設定を管理しています。
ファイナルクラスは特定の状況で利用され、継承を禁止してクラスの拡張を制御するために使用されます。
オープンクラス(open class)は、Kotlinにおいて継承を許可したクラスを指します。 Kotlinのクラスはデフォルトで継承不可(final)となっているため、クラスを継承可能にするには明示的にopen修飾子を使用する必要があります。
上記の例では、MyOpenClass はオープンクラスとして宣言されています。このクラスは他のクラスから継承できます。
上記の例では、MyBaseClass の myMethod は open 修飾子が付いており、このメソッドはオーバーライド可能です。
上記の例では、Shape クラスがオープンクラスとして定義されています。Circle と Square クラスが Shape を継承し、draw メソッドをオーバーライドしています。これにより、各図形クラスは自身の特定の描画方法を持つことができます。
オープンクラスは継承を許可し、クラスの拡張やカスタマイズが可能となります。ただし、使用する際には慎重に設計し、必要なメソッドやプロパティに対してのみopen修飾子を使用することが推奨されます。
列挙型クラス( Enum classes )は、キーワード enum を class に前置して定義します。
Swift/オブジェクト指向#列挙型の例を Kotlin 向けにモディファイしました。
シールドクラス(Sealed class)は、制限されたクラス階層を表現するために使用される Kotlin 特有の機能です。シールドクラスは、特定のサブクラスのみを許容し、新しいサブクラスの追加を防ぎます。これにより、特定の型に対するパターンマッチングが容易になります。
上記の例では、Result クラスはシールドクラスとして宣言されています。このクラスには3つのサブクラスがあります:Success、Error、および Loading。Success と Error はデータクラスで、それぞれデータを保持します。Loading はオブジェクトクラスで、データを保持しません。
上記の例では、Result クラスのサブクラスごとに異なる処理を行う processResult 関数があります。when 式を使用して、特定のサブクラスに対するパターンマッチングを行っています。
シールドクラスは、特に固定されたクラス階層を表現する場合や、特定の型に対する安全なパターンマッチングを行う場合に便利です。
アノテーションクラス(annotation class)は、Kotlinにおいてコードにメタデータを付加するための手段を提供します。これにより、コンパイラや実行時の処理で追加の情報を提供することが可能となります。
アノテーションクラスは、@シンボルを使って宣言されます。アノテーションクラスの主な目的は、アノテーションを作成し、それをコードの要素に適用することです。
上記の例では、MyAnnotation というアノテーションクラスが宣言されています。このアノテーションは、name と version というパラメータを持っています。
アノテーションは、クラスや関数、プロパティなど、さまざまな要素に適用できます。
上記の例では、MyClass クラスとその中の myFunction 関数に MyAnnotation が適用されています。これにより、このクラスや関数に対する追加のメタデータが提供されます。
アノテーションをプロセッシングするためには、リフレクションやKotlinのアノテーションプロセッサを使用することがあります。これにより、アノテーションに関連する処理を行うカスタムロジックを実装できます。
上記の例では、AnnotatedElementを受け取り、その要素に MyAnnotation が適用されているかを調べ、情報を取得しています。
アノテーションクラスは、コードにメタデータを追加し、プロセッシングや設定などの目的で使用されます。
データークラス(Data class)は、Kotlinにおいてデータの保持や操作を目的としたクラスで、copy() メソッドなどがクラスを定義するだけで自動的に生成されます。これにより、不変性やイミュータビリティ(immutable)を維持しながら、簡潔で効果的なデータクラスを作成できます。
上記の例では、Person クラスがデータークラスとして宣言されています。コンストラクタで定義されたプロパティ(name と age)に対して、equals()、hashCode()、toString() などの標準メソッドが自動的に生成されます。
上記の例では、equals() メソッドにより person1 と person2 の内容が一致するか比較され、toString() メソッドによりクラスの内容が文字列として表示されます。また、copy() メソッドを使って一部のプロパティを変更した新しいインスタンスを作成しています。
データークラスが生成される主なメソッドは以下の通りです。
データークラスは、イミュータブルでありながら効果的にデータを操作するための便利な手段を提供します。
Kotlinのインターフェース(interface)は、抽象的なメソッドの宣言と、メソッドの実装を含むことができます。インターフェースは、抽象クラスと異なり状態を保持することができません。プロパティを持つ場合、これらは抽象クラスであるか、アクセサーの実装を提供する必要があります。
上記の例では、MyInterface インターフェースが、抽象メソッド doSomething() とデフォルトのメソッド doSomethingElse()、抽象プロパティ property を宣言しています。
上記の例では、MyClass クラスが MyInterface インターフェースを実装しています。doSomething() メソッドと property プロパティをオーバーライドしています。
上記の例では、C クラスが A インターフェースと B インターフェースの両方を実装しています。複数のインターフェースをカンマで区切って指定することができます。
上記の例では、D インターフェースが A インターフェースと B インターフェースを継承しています。これにより、D インターフェースは A と B のメソッドを含むことになります。
Kotlinのインターフェースは、クラスが異なる振る舞いを持つ場合に簡潔で柔軟な解決策を提供します。異なるインターフェースを実装することで、複数の振る舞いを同じクラスで組み合わせることができます。
インナークラス(Inner class)は、入れ子になった内側のクラスが外側のクラスのメンバーにアクセスすることを可能にします。これにより、外側のクラスと強い結びつきを持ちながら、内部で独自の振る舞いやデータを持つクラスを定義できます。
上記の例では、OuterClass という外側のクラスがあり、その中に InnerClass というインナークラスが定義されています。InnerClass は OuterClass のプロパティにアクセスすることができます。
上記の例では、OuterClass のインスタンスを作成し、そのインナークラスである InnerClass のインスタンスを取得しています。そして、InnerClass のメソッドを呼び出して外側のクラスのプロパティにアクセスしています。
インナークラスは、外部クラスとの緊密な連携が必要な場合や、外部クラスのプライベートなメンバーにアクセスする必要がある場合に有用です。
値クラス(data class)は、イミュータブルでスカラーな値の型を定義するための概念です。プロポーザル段階では inline class と呼ばれていました。値クラスは、プリミティブ型のように振る舞い、同時に型安全性を提供します。
上記の例では、Email という値クラスが宣言されています。この値クラスは、イミュータブルであり、value というプロパティを持っています。
上記の例では、異なるインスタンスの Email クラスを作成し、その値が等しいかを比較しています。値クラスでは、プライマリコンストラクタの引数で値が確定し、その値に基づいて等価性が判定されます。
値クラスは、ドメインモデリングや特定のデータ型を表現する際に有用であり、プロジェクト全体でのコードの理解性や保守性を向上させる役割を果たします。
オブジェクト(object)は、モディファイア・キーワードではありませんが、特殊なクラスの一種であり、一過的な匿名クラスを定義し、その唯一のインスタンスを生成します。オブジェクトはシングルトンのような振る舞いを持ち、一般的には特定の目的に使用されます。
上記の例では、Logger という名前のオブジェクトが宣言されています。このオブジェクトはシングルトンであり、log メソッドを持っています。
上記の例では、Logger オブジェクトの唯一のインスタンスにアクセスし、その log メソッドを呼び出しています。オブジェクトは初回のアクセス時に遅延初期化され、以降は同じインスタンスが再利用されます。
オブジェクトは特定のタスクや目的に対して唯一のインスタンスを提供する場合に利用され、例えばロギングや設定の管理などに適しています。
ジェネリックス( Generics )とは、汎用的なクラス・関数やメソッドを特定の型に対応づける機能のことです。
Kotlinのキーワード( Keywords )は
に分類されます。
以下のトークンは、常にキーワードとして解釈され、識別子として使用することはできません。 このようなキーワードをハード・キーワード( Hard keywords )と呼びます。
以下のトークンは、それが適用される文脈( context )ではキーワードとして機能し、他の文脈では識別子として使用することができます。 このようなキーワードをソフト・キーワード( Soft keywords )と呼びます。
アノテーション使用側ターゲット( Annotation use-site target )は、Kotlinにおいてアノテーションが特定の要素に対して適用される位置を指定する構文です。これにより、生成されるJavaバイトコードにおいてアノテーションがどの要素に適用されるかを正確に指定できます。
以下は、一般的なアノテーション使用側ターゲットの指定方法です。
これらの使用側ターゲットを使うことで、アノテーションが生成される場所を明確に指定することができ、柔軟性を保ちつつ、正確な挙動を得ることができます。
以下のトークンは、宣言の修飾語リスト( modifier lists of declarations )のキーワードとして機能し、他のコンテキストでは識別子として使用することができます。 このようなキーワードをモディファイア・キーワード( Modifier keywords )と呼びます。
以下の識別子は,コンパイラーが特定の文脈で定義したもので、他の文脈では通常の識別子として使用することができます。 このような識別子を特殊識別子( Special identifiers )と呼びます。
Kotlinは以下の演算子( Operators )や特殊特殊シンボル( special symbols )をサポートしています。
Kotlin標準ライブラリー( Kotlin Standard Library )は、以下のような機能を提供します。
Kotlin標準ライブラリーはKotlin自身で書かれています。
kotlin.annotation.*
Kotlinには、Arrayから始まり、Iterable, Collection, List, Set, Mapなどのコレクション型が豊富に用意されています。これらは主に kotlin.collections パッケージで提供されており、ディフォルトインポートなので追加のインポートなしで利用できます。
Iterable インターフェースは、Kotlinの標準ライブラリで使用される反復可能なコレクションの基本的なインターフェースです。このインターフェースは、コレクションが要素の反復処理を可能にするために必要な機能を提供します。
以下に、Iterable インターフェースの主な要素と使用法を示します:
Iterable インターフェースは、Kotlinでコレクションを扱う際に非常に重要であり、様々な反復処理操作を可能にします。
Collection インターフェースは、Kotlinの標準ライブラリで提供されるコレクション型の基本インターフェースの一つです。このインターフェースは、複数の要素を保持するデータ構造を表現し、それらの要素に対する基本的な操作を提供します。
以下に、Collection インターフェースの主な特徴と使用法を示します:
Collection インターフェースは、Kotlinのコレクションの基本的な機能を提供し、様々な種類のコレクションがこれを実装しています。これにより、異なる種類のコレクションを一貫して扱うことができます。
Listは、要素数が固定で要素の値を変更できないコレクションです。
上記の例では、ArrayList を使ってListを生成しています。ArrayListは要素の順序が保持され、可変長の動的な配列を表現します。add メソッドを使用して要素を追加することができます。
mutableListOf() を使って MutableList を生成し、add メソッドを使用して要素を追加しています。MutableListは要素の変更が可能なListです。
これらの例から分かるように、Kotlinのコレクションは型安全で、読み取り専用と可変なコレクションの違いが明確になっています。リストの他にも、SetやMapも用意されており、それぞれの特徴に応じて適切なものを選択できます。
kotlin.collections パッケージのコレクションクラスや関連機能は、さまざまなプログラミングシナリオで利用されます。以下は、kotlin.collections の主なユースケースのいくつかです:
以下は、これらのユースケースの簡単な例です:
これらの例は一部の機能を示すものであり、kotlin.collections のコレクションは、さまざまなプログラミングニーズに対応する強力なツールセットを提供します。
kotlin.collections を使用する際のベストプラクティスはいくつかあります。以下にいくつか挙げてみましょう:
これらのベストプラクティスは、コードの品質、パフォーマンス、保守性を向上させるのに役立ちます。使用ケースによって最適なアプローチを選択することが重要です。
kotlin.comparisons.*
kotlin.io.*
kotlin.ranges.*
kotlin.sequences.*
kotlin.text.*

[TODO:Rangeはコレクションではないので再分類が必要]
println((1..5).javaClass.kotlin)の結果が示す通り、範囲リテラル1..5はclass kotlin.ranges.IntRangeです。 コレクションは、Ranges以外にも、Sequences・Ranges・Lists・Arrays・Sets・Mapsなどがあります。これは網羅していませんし、上記の forプロトコルに従ったクラスを作れば、ユーザー定義のコレクションも作成できます。
Kotlinの標準ライブラリーにあるrepeat関数は、定数回の繰返しが必要な時に便利です。
repeat関数もそうですが、Kotlinにはブロックを受取る関数(やメソッド)があります。
このように、ブロックを取るメソッドを使うとコレクションに関する操作を簡素に書けます。
Kotlinは、言語レベルでコルーチンをサポートし、機能の大部分をライブラリに委ねることで、この問題を柔軟に解決しています。
Kotlin Script では、.jar を生成せず、そのままコードが実行されます。 また、main 関数をエントリーポイントはぜず、スクリプトの書かれた順に評価します。
ビルドツールの Gradle では、従来は Groovy がビルド構成ファイルに使われていましたが、Kotlin Script への移行が進んでいます。