classにつけられるキーワード
classにつけられるキーワード
data
- 値型もどきsealed
- 代数的データ型もどきinner
- Outerクラスの呼び出しが可能となるenum
- Javaのenumopen
- Javaのfinal
の反対。Kotlinの全てのclassはデフォルトでfinal
であるためvalue
- ?
data class
自動導出されるメソッド
プライマリコンストラクタを用いて、以下のメソッドが自動導出される。
equals(
) /hashCode()
ペア - 同値比較化toString()
- 値の文字列化copy()
- 値のコピーcomponentN()
- 値の分割代入
equals()
/ hashCode()
data classは同値比較。値が同じかどうか。
data class UserData(var name: String) val tanaka = UserData("tanaka") val tanaka2 = UserData("tanaka") println(tanaka == tanaka2) // true
classは、デフォルトでは、同一比較。インスタンスが同じかどうか。
class User(var name: String) val tanaka = User("tanaka") val tanaka2 = User("tanaka") println(tanaka == tanaka2) // false
toString()
data classの場合
data class UserData(var name: String) println(UserData("tanaka")) // UserData(name=tanaka)
classの場合
class User(var name: String) println(User("tanaka")) // Classes.User@4ca8195f
copy()
data classの代入はそのまま参照コピーされる
data class UserData(var name: String) val tanaka = UserData("tanaka) val tanaka2 = tanaka // true println(System.identityHashCode(tanaka) == System.identityHashCode(tanaka2)) tanaka2.name = "yoshida" println(tanaka.name) // yoshida
copy()
はインスタンスを複製する。
data class UserData(var name: String) val tanaka = UserData("tanaka) val tanaka2 = tanaka.copy() tanaka2.name = "yoshida" println(tanaka.name) // tanaka
componentN()
分割代入
プライマリーコンストラクタのプロパティ数に応じて、compoennt1()
, ...を自動導出する。
data class UserData(val name: String, val age: Int) val tanaka = UserData("tanaka", 27) // 分割代入 val (name, age) = tanaka println("name: ${name}, age: $age")
通常classとの違い
プライマリコンストラクタは、最低限一つのプロパティを持つ必要がある。
// コンパイルエラー // Data class must have at least one primary constructor parameter data class User()
プライマリコンストラクタのプロパティは、var
もしくは var
である必要がある。
// コンパイルエラー // Data class primary constructor must have only property (val / var) parameters data class User(name: String) { val last_name = name }
abstract
, oepn
, sealed
, inner
をつけることができな
// コンパイルエラー // Modifier 'data' is incompatible with 'open open data class User(val name: String) {}
sealed
代数的データ型の作成。
sealed class Barcode { // dataキーワードを付けることが出来る data class UPC(val p1: Int, val p2: Int, val p3: Int, val p4: Int): Barcode() class QRCode(a: String): Barcode() } var productBarcode = Barcode.UPC(8, 85909, 51226, 3) println(productBarcode)
内部に記述しなくても良い
sealed class Barcode() data class UPC(val p1: Int, val p2: Int, val p3: Int, val p4: Int): Barcode() class QRCode(a: String): Barcode() // 名前空間が取れる var productBarcode = UPC(8, 85909, 51226, 3) println(productBarcode)
whenによるdestructingが対応されていないのでパターンマッチングが微妙ではある。
// 型アノテーションを付ける必要がある //val barcode: Barcode = Barcode.UPC(8, 85909, 51226, 3) val barcode: Barcode = Barcode.QRCode("http://yossan.github.io") // 型におけるパターンマッチングが可能 when(barcode) { is Barcode.UPC -> { if (barcode is Barcode.UPC) { // smart case val (p1, p2, p3, p4) = barcode println("UPC($p1, $p2, $p3, $p4)") } } is Barcode.QRCode -> { if (barcode is Barcode.QRCode) { // smart case val (p) = barcode println("QRCode($p)") } } }
sealedは、interfaceにもつけることも可能
sealed interface Expr
inner
https://kotlinlang.org/docs/nested-classes.html
nested classは、外側のclassに基本アクセスできない
class Outer { private val bar: Int = 1 class Inner { // Unresolved reference: bar fun foo() = bar } }
inner
キーワードを付けることでアクセスが可能となる。
class Outer { private val bar: Int = 1 inner class Inner { fun foo() = bar } } val demo = Outer().Inner().foo()
Annonymouse inner class
object式を使ったインスタンス生成は、Annonyous inner class instanceとなる。
→ 内部でOuterクラスの変数が使える。
window.addMouseListener(object : MouseAdapter() { override fun mouseClicked(e: MouseEvent) { ... } override fun mouseEntered(e: MouseEvent) { ... } })
// This type is final, so it cannot be inherited from // class MyApp: App()
enum
https://kotlinlang.org/docs/enum-classes.html
それぞれのenum定数はobjectになる。