Android Studio 3.0を使い、最近話題のプログラミング言語「Kotlin」の特徴を解説する連載。今回は、変数定義、パッケージ定義とimport、関数、制御文、文字列周りの便利機能などについて。
Android Studioを使い、Kotlin言語の特徴を解説する本連載「Android Studioで始めるKotlin入門」。連載第1回では、Kotlinの大まかな構文を説明しました。今回からは、Kotlin言語の個々の機能について解説します。
なお本連載では、他言語(特にJava)からKotlinに移行するに当たって重要と思われる機能を中心に解説します。本連載で解説されなかった機能については適宜、下記の公式レファレンスを参照してください。
第1回でも少し解説しましたが、Kotlinには2種類の変数定義用のキーワードがあります。varを使うと、他のプログラミング言語と同様、一般的な「変更可能」な変数が定義できます。一方、valを使うと、「変更不可」の変数となります。
valで定義する変数は、厳密には「再代入不可」ということです。そのため、変数の持つプロパティや配列の要素の書き換えなどは問題なく行えます。リスト1にvarとvalの使用例を示します。
var i1: Int = 1 //通常の変数 val i2: Int = 1 //再代入不可変数 i1 = 2 //問題無く書き換え可能 i2 = 3 //再代入不可。コンパイル時に「val cannot be reassigned」エラー発生 //以下は連載第1回で示したイベントハンドラコード val textView = findViewById<TextView>(R.id.myLabel) as TextView …… button.setOnClickListener { v -> //valで定義したtextViewのtextプロパティは書き換え可能 textView.text = "Clicked !" } //arrayOfは引数を並べた配列を作る関数 val ar1: Array<String> = arrayOf("abc", "def", "ghi") //配列の要素も書き換え可能 ar1[2] = "jkl"
valで定義する変数はJavaでいうと「final」を付けて定義した変数に相当するものです。普段自分で書くJavaコードで、変数にfinalを使うのは定数を宣言するときぐらいで、さほど多くないかもしれません。しかし、Kotlinではvalという明確に異なるキーワードが用意されています。
「再代入不可の変数」というと特殊な機能に思えますが、例えばHaskellなどの純粋な関数型言語は「全ての変数が再代入不可である」という特徴を持っています。Scalaなどの関数型言語の影響を受けた言語では、通常の再代入可能な変数と、関数型言語由来の「再代入不可」な変数の両方が扱えるようになっており、Kotlinも同様です。
Kotlinを使い始めたばかりですと「varとvalをどう使い分けるか」について悩むかもしれませんが、例えば「書き換えが必要と分かっている変数以外は、まずはvalで書いてみて、必要に応じてvarに変える」ぐらいの感覚で慣れていくのもいいかもしれません。
「再代入不可」な変数がどのようなメリットを生み出すかについては、興味が出たところでぜひ調べてみてください。関数型言語の奥深さの一部に触れられること間違いなしです。
なお今後解説しますが、Kotlinではクラスにプロパティを持つことができ、プロパティが「読み書き両方可能か」「読み取り専用か」を定義する際にも、それぞれvarとvalを使って区別する仕様となっています。
Javaのpackage文およびimport文は、そのまま使用可能です(リスト2)。
package jp.co.atmarkit.kotlinsample import java.util.*
なお、Kotlinは自動的に表1のパッケージをインポートしています。
パッケージ名 | 概要 |
---|---|
kotlin.* | Kotlinのコア機能。基本データ型などを含む |
kotlin.annotation.* | アノテーション関連機能 |
kotlin.collections.* | List、Set、Mapなどのコレクション関連機能 |
kotlin.comparisons.* | Comparator(比較関数)生成関連機能 |
kotlin.io.* | ファイルおよびストリーム関連機能。println関数もここで定義されている |
kotlin.ranges.* | 範囲(Range)機能(後述) |
kotlin.sequences.* | 遅延処理するコレクション機能 |
kotlin.text.* | 文字列処理および正規表現関連機能 |
java.lang.* | Javaのコア機能(Java VM用にコンパイルした場合) |
kotlin.jvm.* | Javaプラットフォーム用機能(Java VM用にコンパイルした場合) |
Javaで書く場合と同様、Javaの任意のパッケージをimportできるので、使い慣れたライブラリをそのままKotlinでも使用可能です。
int、shortといったクラスではないプリミティブ型を持つJavaに対し、Kotlinはプリミティブ型を持っておらず、表2のような定義となっています。Int、Longなど、Javaのプリミティブ型の先頭を大文字にした名前の型が含まれていますが、これらはJava VM用にコンパイルされた場合、基本的にプリミティブ型として処理されます。
型名 | 概要 |
---|---|
Double | 64bit浮動小数点 |
Float | 32bit浮動小数点 |
Long | 64bit整数 |
Int | 32bit整数 |
Short | 16bit整数 |
Byte | 8bit整数 |
Char | 文字型 |
Boolean | 真偽型 |
Array | 配列型 |
String | 文字列型 |
なお、Kotlinにおいては配列は「Array」クラスで定義されており、「Array<型名>」のように、ジェネリクスを使って型を定義する点が、Javaとは異なっているので注意してください(リスト3)。
val ar1: Array<String> = arrayOf("abc", "def", "ghi") println(ar1[0]) // abcが出力される ar1[2] = "jkl" // インデックスを指定して配列の中身を書き換える println(ar1[2]) // jklが出力される println(ar1.size) //3が出力される。配列数をsizeプロパティで取得可能
配列の内容の取得および書き換えは、Javaと同様に[]でインデックスを指定して行います。Javaでは配列の長さをlength構文で取得できましたが、Kotlinにおいては配列の長さはsizeプロパティで取得します。
なおKotlinでは、Javaのプリミティブ型に相当するInt、Longなどの数値データ型の配列については、別途IntArray、LongArrayなどの専用の配列クラスが存在します。これらはJava VM用にコンパイルされた場合、純粋なプリミティブ型の配列として処理されます。いわゆるボクシング、アンボクシング(プリミティブ型とラッパークラスの自動変換)は発生しません。
//intArrayOfはIntArray型の配列を作る関数 var iar: IntArray = intArrayOf(1,2,3,4,5) println(iar[4]) // 5 iar[4] = 10 println(iar[4]) // 10
何らかの処理を書く場合、「全てクラス内のメソッドとして記述しなければならない」JavaやC#とは異なり、Kotlinは特定の処理の塊をクラスなしで関数として定義できます。前回から使用しているprintln関数、前述の配列を作るarrayOf、intArrayOf関数などが一例です。
関数はパッケージのトップレベルに、クラスと同列に定義できるため、import文でパッケージをインポートすると、そのパッケージで定義された関数も呼び出せるようになります。
import文で関数を呼び出せる辺りは、強いて言えば、Java SE 5.0で導入された「staticインポート」やC# 6.0の「using static」に少し似ているかもしれませんが、クラスなしで関数が存在する点などは、まずクラスありきのJavaやC#とは大きく異なる部分ですので注意してください。
Kotlinには「型推論」と呼ばれる機能があり、変数を定義する際にデータ型が推測可能な場合、データ型指定を省略できます。
//普通の定義 val message: String = "FizzBuzz start!" val a1: Int = 1; var iar1: IntArray = intArrayOf(1,2,3,4,5) //型推論を使った定義 val message2 = "FizzBuzz start!" val a2 = 1; var iar2 = intArrayOf(1,2,3,4,5)
C#プログラマーであれば、C# 3.0以降でサポートされたvarキーワードと同様の機能といえば、その利便性の高さを理解できることでしょう。Javaにおいては、Java 7で「ジェネリック型」については型推論がサポートされたものの、通常の変数定義においては依然として「型名 変数名 = new 型名();」のように冗長な記述を強制され続けています。
そんなJavaプログラマーにとっての朗報です。Kotlinを使えば「型推論を使えない言語なんて……」と他言語プログラマーに揶揄(やゆ)されることもなくなりますね。
なお、2018年3月20日(米国時間)にリリースされたJava SE 10では、ローカル変数型推論がサポートされるようになりました。
Copyright © ITmedia, Inc. All Rights Reserved.