LoginSignup
2
1

More than 5 years have passed since last update.

Kotlinまとめ - 文法詳解 - クラスとそのメンバ

Last updated at Posted at 2018-07-17

クラスの定義

class MyClass

val myClass = MyClass() // デフォルトのコンストラクタが生える

Kotlinではnewキーワードを付ける必要はない
newは予約語ではない

メソッド

  • 定義方法は関数と同じ
  • 呼び出しはインスタンス.メソッド名
class Greeter {
    fun greet(name: String) {
        println("Hello, $name")
    }
}

val greeter = Greeter()
greeter.greet("Kotlin")

プロパティ

  • 定義方法は変数と同じ
  • オブジェクトの特性や性質を表すデータをやり取りするための窓口
class Person {
    var name: String = ""
    var age: Int = 0
}

val hanako = Person()
println(hanako.name) // ""
println(hanako.age)  // 0

hanako.name = "hanako"
hanako.age = 25

println(hanako.name) // "hanako"
println(hanako.age)  // 25

バッキングフィールド

  • 上記の例のようなPersonクラスのnameageには自動的にバッキングフィールドが生成される
  • 例えば、nameとして保持する文字列オブジェクトへの参照をバッキングフィールドが持っている
  • バッキングフィールドを持たないプロパティを定義することも可能
バッキングフィールドを持たない`nameLength`追加
class Person {
    var name: String = ""
    var age: Int = 0
    val nameLength: Int
        get(): Int {
            return this.name.length
        }
}

これはSwiftでいうコンピューテッドプロパティに似ている

カスタムセッターを定義することも可能

class Person {
    var name: String = ""
        set(value) {
            println("${value}がセットされました")
            field = value
        }
    var age: Int = 0
    val nameLength: Int
        get(): Int {
            return this.name.length
        }
}
  • fieldはバッキングフィールドを表す暗黙の変数
    • name = valueとすると無限にカスタムセッターが呼ばれてクラッシュする

遅い初期化

  • バッキングフィールドをもつプロパティは初期化が必須
  • どうしても初期化を遅らせたい場面がある
    • DIやUnitテストのときとか…
  • varのみ可能
  • 初期化前にlateinitの変数にアクセスするとkotlin.UninitializedPropertyAccessExceptionをスローする
class MyClass {
    lateinit var foo: String
}

this

  • メソッドやプロパティをまとめてメンバと呼ぶ
  • メンバへのアクセスは目的のオブジェクトへの参照.メンバ名
  • this.メンバ名とすることで、自身のオブジェクトのメンバにアクセスできる
  • thisは省略可能

コンストラクタとイニシャライザ

  • 分数クラスRationalの初期化に分子numeratorと分母denominatorを受け取る例
class Rational constructor(n: Int, d: Int) {
    val numerator: Int = n
    val denominator: Int = d
}

val half = Rational(1, 2)
println(half.numerator)
println(half.denominator)

コンストラクタの引数をそのままプロパティにしたい場合は、引数にvalvarをつける

class Rational(val numerator: Int, val denominator: Int)

セカンダリコンストラクタ

  • 今までのコンストラクタはプライマリコンストラクタ
  • 分母の指定がない場合はデフォルトで1になるセカンダリコンストラクタを定義
class Rational(val numerator: Int, val denominator: Int) {
    constructor(numerator: Int): this(numerator, 1)
}

// 今回の場合だとデフォルト引数のほうが早い
class Rational(val numerator: Int, val denominator: Int = 1)

イニシャライザ

  • インスタンス生成の際に実施しておきたい処理
class Rational(val numerator: Int, val denominator: Int = 1) {
    init {
        // 要求に反した場合、例外をスローする標準ライブラリの関数
        // ∴分母が0になった場合、IllegalArgumentExceptionをスローする
        require(denominator != 0)
    }
}

エクステンション

既存クラスに対して、その定義に手を入れずにメソッドを追加できる→拡張関数

fun String.countWords(): Int = this.split("""\s+""".toRegex()).size

"I like  Kotlin".countWords() // 3

拡張プロパティもOK
thisは省略可能

val String.wordsCount: Int
    get() = split("""\s+""".toRegex()).size

← 文法詳解 - オブジェクトからクラスへ || 文法詳解 - 継承と抽象クラス →

2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1