転職を繰り返したサラリーマンの多趣味ブログ

30才未経験でSEに転職した人の多趣味ブログ

Kotlinまとめ

変数と定数

// 変数
var a : Int = 10000

// 定数
val c : Double = 12345.6 

文字列

// 文字列比較は「==」で行う
if (str == "Kotlin")

// 文字列テンプレート
val i = 10
print("i = $i") // i = 10と出力される

// 文字列テンプレート2
val s = "Kotlin"
printl("$s length is ${s.length}) // Kotlin length is 6 と出力される。{}をつけないと、Kotlin length is Kotlin.lengthと表示される

型変換

// 文字列からInt型へ
val str = "64"
val intVal: Int = str.toInt()

// 文字列からInt型へ
val str = "Kotlin"
val intVal: Int? = str.toIntOrNull() // 変換できない場合は変数にNULLを設定

// 数値から文字列へ
val num = 128
val intStr: String = num.toString()

// 数値同士の変換
val i: Int = 100
val l: Long = i.toLong() // 明示的に変換が必要

null許容型とnull非許容型

// 以下の場合はエラーになる
var text: String = null

// 正しくは以下のような記述が必要
var text: String? = null

// null許容型の変数の場合、String型のメソッドやプロパティをそのままでは使用できないなどの制限が発生する

配列

// Arrayクラスを使い、arrayOf関数で配列の生成と初期化を実行
val arrayofInt: Array<Int> = arrayOf(1,2,3,5,8)
for (i in arrayofInt) print("$i,")

if式

val c = 10
val d = 20
if (c > d) {
    print("c")
} else {
    print("d")
}

when式

val a = 4
when(a) {
    1 -> println("a == 1")
    2,3 -> println("a == 2 or 3")
    in 10..20 -> println("a is in the range")
    !in 20..30 -> println("a is outside the range")
    else -> println("otherwise")
}

for文

for(i in 1..4)

// 配列を使う場合
val a = arrayOf(1,2,3,10,100)
for(i in a.indices) {
    print("a[$i]=${a[i]}")
}

while文

var x = 0
while(x < 10)

// do-while文
var i = 7
do {
    
}while(i > 4)

リスト

// 読み込み専用リスト
val items: List<Int> = listOf(1, 2, 3)
println(items.get(0))
println(items[1])
println(items.size)

// 変更可能なリスト
val numbers:MutableList<Int> = mutableListOf(1,2,3)
numbers.add(4) // リストの末尾に4を追加
numbers.remove(4) // 一致する要素を削除

セット

// 特徴:要素の順番をもたず、要素の重複も不可

// 読み取り専用セット
var strings:Set<String> = setOf("A", "B", "C")
println(strings)

// 変更可能セット
var strings: MutableSet<String> = mutableSetOf("x", "y", "z")
strings.add("A")
strings.remove("x")

マップ

// 読み取り専用のマップ
val fruits:Map<String, Int> = mapOf("apple" to 1, "orange" to 2, "banana" to 3)

// 変更可能なマップ
val fruits: MutableMap<String, Int> = mutableMapOf("apple" to 1, "orange" to 2, "banana" to 3)
println(fruits.get("apple"))
println(fruits["orange"])
fruits.put("melon",4) // 要素の追加
fruits.remove("banana") // 要素の削除

関数

// fun 関数名(引数:型,・・・):戻り値
fun times(a: Int, b: Int): Int {
    return a * b
}
// 関数の呼び出し
// Kotlinではクラスに属さない関数を作成できる
times(2, 5)

// 戻り値がなく、2番目の引数をデフォルト設定する場合
fun printTimes(a: Int, b:Int = 2):Unit{}
printTimes(10)

ラムダ式と関数型

ラムダ式:{引数 -> 処理}

// ラムダ式は変数に格納可能。この時の変数を関数型と呼ぶ
var minus = {x: Int, y: Int -> x - y}
minus(3, 1) // 結果は2

// 変数plusは「(Int, Int) -> Int」型
var plus:(Int, Int) -> Int = {x:Int, y:Int -> x + y}
plus(5, 2)

// 暗黙の引数it
// 引数一つの場合は、引数を省略し引数itを使用できる
// itを使用しない場合はvar double:(Int)->Int = {x:Int -> x * 2}とかく
var double: (Int)->Int = {it * 2}
double(5)

// 関数型を引数に持つ関数
fun doLambda(x: Int, y:(Int) -> Int) = y(x)
doLambda(5, {it * 2})

クラスとインターフェイス

クラスの定義:class クラス名{}
※publicがデフォルト

// インスタンス生成
class dog{}
val dog = Dog()

インターフェイスの定義:interface インターフェイス名{定義}
Kotlinのインターフェイスは、抽象メソッドだけでなく具体的な処理も記述できる

プロパティ

Javaのフィールドとセッター/ゲッターを合わせたような機能

var dog = Dog()
dog.name = "Pochi" // プロパティに値を設定
println(dog.name) // プロパティから値を取得

コンストラク

プライマリコンストラクタ:クラス宣言でクラス名の後ろにコンストラクタの引数のみを記載する。処理ブロックをもたないため、処理を行う場合はinitブロックに記載。
セカンダリコンストラクタ:処理ブロックを持つため、その他の処理も記載可能。

class Dog(val name: String) {}

イニシャライザ

class Dog(val name: String) {
    init{
        print("The dog's name is $name")
    }
val dog = Dog("Pochi") // ここでイニシャライザが呼ばれる

クラスの継承

class クラス名(プライマリコンストラクタ):親クラス名(コンストラクタ引数)

open class Person(val name: String) {} // 親クラス
class Student(name: String, var degree: String): Person(name) {} // 子クラス
val student = Student("Sato", "Bechelor") // インスタンスの取得

インターフェイスの実装

class クラス名(プライマリコンストラクタ):インターフェイス
※Kotlinのインターフェイスでは抽象メソッドだけでなく、具体的な処理を含むメソッドも定義可能。

interface Pet {
    fun eat()
    fun showName() = println("I'm Pet")
}

class Cat : Pet {
    override fun eat() = println("I'm eating")
}

型チェックとスマートキャスト

fun getLen(obj: Any) : Int? {
    // isでStringかどうかチェック
    if ( obj is String) {
        // チェック後はStringとしてふるまう
        return obj.length
    }
 return null
}

継承関係のあるオブジェクトのキャスト

// 親クラス
open class Person(val name: String) { }
// 子クラス
class Student(name: String, var degree: String): Person(name) {}
// 親クラスの変数に子クラスのインスタンスを生成
var person: Person = Student("Sato", "Bechelor")
// 子クラスへキャスト
var student: Student = person as Student

// as?の使い方
var person: Person = Student("Sato", "Bechelor")
// 例外が発生せずに、nullがセットされる
var student = person as? Int

objectキーワード

objectキーワードを使うと、クラスの宣言とそのインスタンス生成を一気に行う。
■シングルトンの実現

object MyProfile {
    処理内容
}

// objectを使用するにはオブジェクト名を使う
MyProfile.メソッド名

■コンパニオンオブジェクト

class Person(val name: String) {
    companion object {
        fun printMe() = println("Hello")
    }
}

// スタティックメソッドのように扱える
Person.printMe()

■オブジェクト式
無名インナークラスを簡単に記述するための機能

SAM変換

Javaインターフェイスで、メソッドを1つしか持たないものをSAM(Simgle Abstract Method)インターフェイスと呼ぶ。
KotlinではSAMインターフェイスを引数としたメソッドを、ラムダ式で置き換えることをSAM変換と呼ぶ。

NULL安全

var s: String? = null
// The length of null is nullと出力される
print("The length of $s is ${s?.length}")

エルビス演算子

// 変数sがNULLでなければsを返し、sがNULLならdefaultという文字列を返す
val t : String = s ?: "default"

スコープ関数

■with関数
with(対象オブジェクト){処理}

with(Dog("Pochi")) {
    age = 10     // プロパティに値を設定
    message()   // メソッドの利用
}

■apply関数
対象オブジェクト.apply{処理}

Dog("Pochi").apply{
    age = 10
}.message()

■let関数
対象オブジェクト.leg{処理}

var output = name?.let{
    var upperCase = it.toUpperCase()
    var len = it.length
    "$upperCase $len"
}
print(output)

■run関数
対象オブジェクト.run{処理}

var output = name?.run{
    "${toUpperCase()} $length"
}
print(output)

Pair

val p = Pair("apple", 1)
println("the number of ${p.first} is ${p.second} // the number of apple is 1と出力される

拡張関数

fun 型名.関数名(引数):戻り値{処理}