Kotlinのクラス（社内勉強会用）

KotlinのClass関連の言語仕様を駆け足で紹介。
Javaは知っている人向け。

参照: https://kotlinlang.org/docs/reference/classes.html

---

# Class

```kotlin
class Animal {
    var name: String? = null

    override fun toString(): String {
        return "Animal (name is $name)"
    }
}
```

```kotlin
val cat = Animal()
cat.name = "tama"
print(cat) // Animal (name is tama)
```

- デフォルトでAnyクラスを継承
- 明示的なコンストラクタなし
- デフォルトでpublic
- デフォルトで非open

---

# Any Class

```kotlin
public open class Any {
    public open operator fun equals(other: Any?): Boolean
    public open fun hashCode(): Int
    public open fun toString(): String
}
```

- The root of the Kotlin class hierarchy. Every Kotlin class has Any as a superclass.
- Note: `Any` is not `java.lang.Object`; in particular, it does not have any members other than `equals()`, `hashCode()` and `toString()`.
    - 例えば `clone()` や `wait()` など

--- 

# Constructor

```kotlin
class Animal(name: String) { // primary constructor
    var name: String = name // property initialization

    override fun toString(): String {
        return "Animal (name is $name)"
    }
}
```

```kotlin
class Animal(var name: String) { // primary constructor & property initial
    override fun toString(): String {
        return "Animal (name is $name)"
    }
}
```

```kotlin
class Animal(var name: String) { // primary constructor & property initial
    var age: Int? = null

    constructor(age: Int) : this("no name") { // secondary constructor
        this.age = age
    }

    override fun toString(): String {
        return "Animal (name is $name)"
    }
}
```

---

# Visibility Modifiers

|Modifiers|Visibility|
|---|---|---|
|`public` (default)|everywhere|
|`internal`|module|
|`private`|file|

```kotlin:lib.kt
package com.access_company.myapplication.lib

class Foo
internal class Bar
private class Baz
```

```kotlin:app.kt
package com.access_company.myapplication.app // 同module 別package

import com.access_company.myapplication.Foo // OK
import com.access_company.myapplication.Bar // OK
import com.access_company.myapplication.Baz // Compile Error
```

- Javaと違い、package privateというものはない
- `Module`: Gradle source set などの、一緒にコンパイルされるkotlinファイルの集まり
- file privateは便利

---

# Inheritance

デフォルトでは継承できず、`open`の明示が必要

```kotlin
open class Animal(var name: String)

class Human(name: String) : Animal(name) // super class constructor
```

- `open`: Javaの`final`の逆

---

# Nested Class

Javaの `static inner class` と同じ

```kotlin
class Animal(var name: String) {
    private var nameHolder = NameHolder(name)

    override fun toString(): String {
        return return "Animal (name is ${nameHolder.toUpperCase()})"
    }

    private class NameHolder(var name: String) {
        fun toUpperCase(): String {
            return name.toUpperCase()
        }
    }
}
```

```kotlin
class Animal(var name: String) {
    private var nameHolder = NameHolder(name)

    override fun toString(): String {
        return return "Animal (name is ${nameHolder.toUpperCase()})"
    }

}
private class NameHolder(var name: String) {
    fun toUpperCase(): String {
        return name.toUpperCase()
    }
}
```

file privateなクラスでいいじゃんという気もする

---

# Inner Class

Javaの staticでない `inner class` と同じ

```kotlin
class Animal(var name: String) {
    private var nameHolder = NameHolder()

    override fun toString(): String {
        return return "Animal (name is ${nameHolder.toUpperCase()})"
    }

    private inner class NameHolder() {
        fun toUpperCase(): String {
            return name.toUpperCase()
        }
    }
}
```

---

# Data Class

データを保持するのに便利なクラス

```kotlin
data class Animal(var name: String)
```
The compiler automatically derives the following members from all properties declared in the primary constructor:

- equals()/hashCode() pair
- toString()

```kotlin
Animal("tama") == Animal("tama") // true
print(Animal("tama")) // Animal(name=tama)
```

---

# Sealed Class

同じファイル内でしか継承できないクラス

```kotlin
sealed class Animal(val name: String)
class Cat(name: String) : Animal(name)
data class Human(val firstName: String, val lastName: String) : Animal("$firstName $lastName")
```

```kotlin
val animal: Animal = Cat("tama")

val nickname: String = when(animal) {
    is Cat -> "${animal.name}ちゃん"
    is Human -> "${animal.lastName}さん"
    // the `else` clause is not required
}
```

---

thanks