備忘録用。
Kotlinプログラミングを読んで気になったKotlinの文法や仕様をアウトプット。
ちょっとだけ掘り下げて調べた箇所もあり。
本書の 2章 ~ 4章 まで。(1章は開発環境構築だったのでスキップ)
サンプルコードは本書から書き換えて記述している。
Kotlinの変数・関数宣言の仕方
変数
// 変数宣言キーワード 変数名:型定義 = 代入値
var age:Int = 20
関数
// 可視性修飾子 関数宣言キーワード 関数名(関数パラメータ):戻り値の型{
// ...
// }
private fun hello(name:String):String {
return "Hello, $name san"
}
2章 変数と定数と型
2.5 型推論
val playerName: String = "Estragon"
上記のような記述はInteliJだと String
部分が灰色となり、「冗長な記述をしている」のようなメッセージが出る。
これは、型宣言時に String
のデータを代入しているため、コンパイラが型情報を推論しているため。
IntellJでは 変数名にマウスカーソルをあわせて Command + Shift
で型情報を表示できる。
2.6 コンパイル時定数
名前の通りプログラムをコンパイルするときにその変数が代入される。(mainや他の関数の変数は 実行時(runtime) に代入される。
関数・クラスの外側に定義する。
String, Int等の基本型のみサポートされる。ほかだとコンパイル時という保証が得られない。
const
修飾子を使う。
const val MAX_EXPRERIENCE: Int = 5
fun main(args: Array<String>) {
println(MAX_EXPRERIENCE) // 5
}
同パッケージの階層で同じ定数名は使えない。
private
等の、アクセス修飾子を付けない限り、どこからでもアクセスできてしまう。
なので、むやみに乱用するとグローバル汚染が懸念される。
もっと知りたい? KotlinにおけるJavaのプリミティブ型
Javaと違い、Kotlinは参照型しかない。プリミティブ型が無い。
ただし、コンパイラは可能であれば、Javaのバイトコードでプリミティブを使う。これはプリミティブ型のほうが性能が高いため。
3章 条件文
3.8 範囲
範囲(range) をつかって一連の値を表現できる。
..
を使うことで、範囲を表現できる。
in
キーワードを使うことで、値が範囲に含まれているかチェックする。
in 1..3
なら 1,2,3 が含まれる。
println(2 in 1..3) // true
println(4 in 1..3) // false
for (i in 1..3) print(i) // 123
for (i in 3 downTo 1) print(i) // 321
for (i in 1..8 step 2) print(i) // 1357
文字の範囲チェックもできる。
println('c' in 'a'..'c') // true
println('d' in 'a'..'c') // false
Dateの範囲チェックもできたりする。(ただし、downTo
等の関数は使えないので注意)
val start = Date.valueOf("2019-01-01")
val end = Date.valueOf("2019-12-31")
println(Date.valueOf("2019-08-01") in start..end) // true
範囲(..
)を使ってList生成したりはよく使いそう。
(11..15).toList().forEach({ i -> println(i) }) // 11 12 13 14 15
3.9 when式
JavaでいうSwitch文。
3つ以上の分岐があるならwhenを使ったほうがキレイになる。
// 引数あり
val str = "hoge"
when (str) {
"hoge" -> println("ほげ")
"huga" -> println("ふが")
else -> println("ぴよ")
}
// 引数なし
val str = ""
val result = when {
str == null -> "str is null"
str.isEmpty() -> "str is Empty"
str == "hoge" -> "ほげ"
else -> "ぴよ"
}
println(result)
3.10 文字列テンプレート
$変数名
とすれば文字列の中に変数を埋め込めむことができる。
スペース等の区切り文字が無いもしくは、中で式を書きたいときは ${}
を使う。
println("私は" + name + "、" + age + "歳です。") // 私はマイク、20歳です。
println("私は$name、${age}歳です。") // 私はマイク、20歳です。
// 文字列テンプレートの中に式を書くこともできる
println("私は$name、${if (age >= 20) "成人" else "未成年"}です。") // 私はマイク、成人です。
4章 関数
4.2 関数の解体
関数は private
など明示的に指定しないとデフォルトで public
とみなす。
4.6 デフォルト引数
引数を指定されないときに使うデフォルト値
private fun calcTax(taxRate: Double = 0.10) {
val price = 1000
println("${price}円 の商品の消費税は ${price * taxRate}円です。")
}
calcTax() // 1000円 の商品の消費税は 100.0円です。
calcTax(0.08) // 1000円 の商品の消費税は 80.0円です。
4.7 単一式関数
1つの式しか持たない関数は {}
を省略して =
で記述できる。
- 例1
private fun calcTax(price: Int = 1000, taxRate: Double = 0.10) {
println("${price}円 の商品の消費税は ${price * taxRate}円です。")
}
↓
private fun calcTax(price: Int = 1000, taxRate: Double = 0.10) =
println("${price}円 の商品の消費税は ${price * taxRate}円です。")
- 例2
when文も1つの式扱いなので =
で記述できる。
private fun rate(score: Int): String {
return when (score) {
100 -> "great!"
in 40..99 -> "good"
else -> "bad.."
}
}
private fun rate(score: Int): String = when (score) {
100 -> "great!"
in 40..99 -> "good"
else -> "bad.."
}
4.8 Unit関数
Javaでいう voidに近い、でも厳密には違うらしい。
- void: 何も返さない
- Unit: 値を返さない関数
Unitだと何も返さないジェネリックス関数を書けるメリットになるらしい。
あまりピンとこない...17章で詳しく説明されるので一旦保留。
4.9 名前付き引数
下記の例は、同じ関数を同じ引数で呼び出している。
// 名前付き引数
introduce(from = "大阪", name = "太郎", age = 20)
private fun introduce(name: String, age: Int, from: String) {
println("私は $name、 $age 歳です。出身は $from です。")
}
- 名前付き引数は関数ヘッダの並びと関係無い順番で渡せる。
- どこの引数がどの関数パラメータに値を提供しているのかが分かるので、コードが明瞭になる。
4.10 Nothing関数
関数が正常終了しないことを保証する。つまりExceptionが発生する関数。
例外をThrowする等の理由で決して呼び出し側に戻らない関数。
標準ライブラリにTODO関数が入っており、これの返却型はNothing。
NotImplementedError
は発生する。
TODO("TODO") // NotImplementedError
println("Hello World") // 実行されない