0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Kotlin のクラス

0
Posted at

Kotlin を勉強中なので、自分用まとめ

クラス

クラスの定義とインスタンス化

class MyClass {
    private var str = "aaa"
    var num = 1
    
    fun showData () {
        println("Str = ${str}, Num = ${num}")
    }
}

val sample = MyClass()
sample.showData()

アクセス修飾子

修飾子 説明
public 全てのクラスからアクセス可能
protected クラスとサブクラス内からアクセス可能
internal 同じモジュール内のクラスからアクセス可能
private クラス内からのみアクセス可能

プロパティ

Kotlin ではフィールド(クラス内変数)が使えないが、代わりにプロパティが使える

  • プロパティ
    • アクセサー(getter/setter)を持つ
    • getter / setter の記述は省略可能
    • getter / setter を省略した場合、単純な値の get / set が提供される

プロパティの定義

var プロパティ名: 型 = 初期値
  getter 関数
  setter 関数
class MyClass {
    var num = 1
      set(value) {  // 引数は value が使われる
          if (value < 0) {
              println("Illegal Value")
          } else {
              field = value
          }
      }
}

fun main() {
    val sample = MyClass()
    
    sample.num = -2     //=> Illegal Value
    sample.num = 5
    println(sample.num) //=> 5
}

コンストラクタ

プライマリコンストラクタ

クラスに一つだけ記述されるコンストラクタ

class MyClass constructor(str: String, num: Int) {
    var str: String
    var num: Int
    
    init {
        this.str = str  // プロパティと引数が同じ名前のときは this を付けて差別化する
        this.num = num
    }

    fun showData () {
        println("Str = ${str}, Num = ${num}")
    }
}

val sample = MyClass("abc", 3)
sample.showData()  //=> Str = abc, Num = 3

プライマリコンストラクタのキーワードは省略可能

class MyClass (str: String, num: Int) {}

var / val を付けると、宣言と初期化を同時に行える

class MyClass (var str: String, var num: Int) {
    fun showData () {
        println("Str = ${str}, Num = ${num}")
    }
}

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

ひとつのクラスに2つ以上のコンストラクタを定義

初期化の処理を分岐させるような場合に使用される

class MyClass constructor(var str: String, var num: Int) {
    constructor(str: String):this(str, 1) {}
    constructor():this("xyz") {}
    fun showData () {
        println("Str = ${str}, Num = ${num}")
    }
}

val sample1 = MyClass("abc", 3)
val sample2 = MyClass("aaa")
val sample3 = MyClass()

sample1.showData() //=> Str = abc, Num = 3
sample2.showData() //=> Str = aaa, Num = 1
sample3.showData() //=> Str = xyz, Num = 1

継承

継承元のクラス、メソッドには、open 修飾子が必要

open class BaseClass(var a: Int) {
    open fun showData(){
        println(this.a)
    }
}

class MyClass(a: Int, var b: String) :BaseClass(a)

val instance = MyClass(1, "abc")
instance.showData()  //=> 1

オーバーライド

override 修飾子をつけることで、継承元のメソッドを上書きする

open class BaseClass(var a: Int) {
    open fun showData(){
        println(this.a)
    }
}

class MyClass(a: Int, var b: String) :BaseClass(a) {
    override fun showData(){
        println("${this.b}")
        super.showData()  // 継承元のメソッドを呼び出す
    }
}

val instance = MyClass(1, "abc")
instance.showData()  //=> abc, 1

抽象クラス

abstract 修飾子を付けることで、抽象クラス・メソッドになる

抽象メソッドは、実装部分を持つことはできない

abstract class AbstClass(var a: Int) {
    abstract fun showData()
}

class MyClass(a: Int, var b: String) :AbstClass(a) {
    override fun showData(){
        println("${this.b}, ${this.a}")
    }
}

val instance = MyClass(1, "abc")
instance.showData()

データクラス

データを保持するだけで、処理を持たないクラス

data class MyClass(val a: Int, val b: String)

データクラスの条件

  • 一つ以上の引数を持つ
  • 引数にはすべて varval を付与
  • abstract open sealed inner 修飾子は付けられない

データクラスにはいくつかのメソッドが用意されている

equals メソッド

同値性を確認する

data class MyClass(var a: String = ""){
    var b: Int = 0
}

val m1 = MyClass("abc")
m1.b = 1
val m2 = MyClass("abc")
m2.b = 2

println(m1 == m2)  //=> true  (== で equals メソッドが呼ばれる)

toString メソッド

データクラスのオブジェクトを文字列化

println 関数を実行時に暗黙で呼ばれる

componentN

プロパティの値を個々の変数に分解する

val t = Triple("a", "b", 10)

println(t.component1())  //=> a
println(t.component2())  //=> b
println(t.component3())  //=> 10

分割代入で使用されている

val t = Triple("a", "b", 10)
val (x, y, z) = t
println(x)  //=> a
println(y)  //=> b
println(z)  //=> 10

copy

オブジェクトのコピー

data class MyClass(val x: String, val y: String, val z: Int)

val m1 = MyClass("a", "b", 1)
val m2 = m1.copy(x = "c")

println(m2)  //=> MyClass(x=c, y=b, z=1)

オブジェクト式

再利用しないクラス

object {クラス本体}
object:  基底クラス or インターフェイス {クラス本体}

Android 開発において、ボタンクリック時の処理を定義するときなどに使用できる

btn.setOnClickListener の引数はクラスである必要があるが、通常は他のボタンでは再利用しないので、オブジェクト式が使える

btn.setOnClickListener(object: View.OnClickListener {
  override fun onClick(view: View) {
    // ボタンクリック時の処理
  }
})

SAM(Single Abstract Method)インターフェース

  • 抽象メソッドをひとつだけ持つインターフェース
  • ラムダ式で置き換えられる
// 上プログラムをラムダ式で置き換えたもの
btn.setOnClickListener{ クリックされた時の処理 }

オブジェクト宣言

ひとつのインスタンスしか持たないクラス

object オブジェクト名 {オブジェクト本体}
object MyObject {
    val x = "a"
    var y = 10

    fun showData(){
        println("${x}, ${y}")
    }
}
    
MyObject.y = 20
MyObject.showData()  //=> a, 20

ジェネリック型

データ型に依存しない、汎用的なコード記述

class MyClass<T>(var value:T) {
    fun getVal(): T {
        return value
    }
}

val m1 = MyClass<String>("aaa")
val m2 = MyClass<Int>(10)
println(m1.getVal())  //=> aaa
println(m2.getVal())  //=> 10
m1.value = 1  // Error

ジェネリック関数

関数の呼び出し時に引数と戻り値の型を決める

fun <T> myFunction(arr: Array<T>): T = arr[arr.size - 1]

val a1 = arrayOf(1, 2, 3)
val a2 = arrayOf("a", "b", "c")

println(myFunction<Int>(a1))
println(myFunction<String>(a2))

ネストクラス

クラスの中にクラスを定義することができる

クラスA内で定義されたクラスBは、クラスA 内部からしか呼ぶことができない

class MyClassA{
    private class MyClassB{
        fun show () = println("class B")
    }
    
    fun run() {
        val instB = MyClassB()
        instB.show()
    }
}

val instA = MyClassA()
instA.run()  //=> class B
0
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
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?