Skip to content

クラス

Kotlinは、クラスとオブジェクトを使ったオブジェクト指向プログラミングをサポートしています。オブジェクトは、プログラム内でデータを格納するのに役立ちます。 クラスを使用すると、オブジェクトのための一連の特性を宣言できます。クラスからオブジェクトを作成する際、これらの特性を毎回宣言する必要がないため、 時間と労力を節約できます。

クラスを宣言するには、classキーワードを使用します。

kotlin
class Customer

プロパティ

クラスのオブジェクトの特性はプロパティで宣言できます。クラスのプロパティは以下の場所で宣言できます。

  • クラス名の後の丸括弧 () 内。
kotlin
class Contact(val id: Int, var email: String)
  • 波括弧 {} で定義されたクラス本体内。
kotlin
class Contact(val id: Int, var email: String) {
    val category: String = ""
}

クラスのインスタンスが作成された後に変更する必要がない限り、プロパティは読み取り専用 (val) として宣言することをお勧めします。

丸括弧内にvalvarなしでプロパティを宣言することもできますが、これらのプロパティはインスタンスが作成された後にはアクセスできません。

  • 丸括弧 () 内に含まれる内容はクラスヘッダーと呼ばれます。
  • クラスプロパティを宣言する際に、末尾のコンマを使用できます。

関数パラメータと同様に、クラスプロパティはデフォルト値を持つことができます。

kotlin
class Contact(val id: Int, var email: String = "[email protected]") {
    val category: String = "work"
}

インスタンスの作成

クラスからオブジェクトを作成するには、コンストラクタを使用してクラスのインスタンスを宣言します。

デフォルトでは、Kotlinはクラスヘッダーで宣言されたパラメータを持つコンストラクタを自動的に作成します。

例:

kotlin
class Contact(val id: Int, var email: String)

fun main() {
    val contact = Contact(1, "[email protected]")
}

この例では:

  • Contactはクラスです。
  • contactContactクラスのインスタンスです。
  • idemailはプロパティです。
  • idemailはデフォルトのコンストラクタと共にcontactを作成するために使用されます。

Kotlinのクラスは、自分で定義したものを含め、多くのコンストラクタを持つことができます。複数のコンストラクタを宣言する方法の詳細については、コンストラクタを参照してください。

プロパティへのアクセス

インスタンスのプロパティにアクセスするには、インスタンス名の後にピリオド . を付けてプロパティの名前を記述します。

kotlin
class Contact(val id: Int, var email: String)

fun main() {
    val contact = Contact(1, "[email protected]")
    
    // プロパティ email の値を表示します
    println(contact.email)           
    // [email protected]

    // プロパティ email の値を更新します
    contact.email = "[email protected]"
    
    // プロパティ email の新しい値を表示します
    println(contact.email)           
    // [email protected]
}

プロパティの値を文字列の一部として連結するには、文字列テンプレート (). 例えば:

kotlin
println("Their email address is: ${contact.email}")

メンバー関数

オブジェクトの特性の一部としてプロパティを宣言するだけでなく、メンバー関数でオブジェクトの動作を定義することもできます。

Kotlinでは、メンバー関数はクラス本体内で宣言する必要があります。インスタンスでメンバー関数を呼び出すには、インスタンス名の後にピリオド . を付けて関数名を記述します。例:

kotlin
class Contact(val id: Int, var email: String) {
    fun printId() {
        println(id)
    }
}

fun main() {
    val contact = Contact(1, "[email protected]")
    // メンバー関数 printId() を呼び出します
    contact.printId()           
    // 1
}

データクラス

Kotlinにはデータクラスがあり、データの格納に特に役立ちます。データクラスはクラスと同じ機能を持っていますが、自動的に追加のメンバー関数が提供されます。これらのメンバー関数を使用すると、インスタンスを読みやすい出力に簡単に表示したり、クラスのインスタンスを比較したり、インスタンスをコピーしたりできます。これらの関数が自動的に利用できるため、各クラスで同じボイラープレートコードを作成する時間を費やす必要がありません。

データクラスを宣言するには、dataキーワードを使用します。

kotlin
data class User(val name: String, val id: Int)

データクラスの最も有用な事前定義メンバー関数は次のとおりです。

関数説明
toString()クラスインスタンスとそのプロパティの読みやすい文字列を出力します。
equals() または ==クラスのインスタンスを比較します。
copy()別のクラスインスタンスをコピーして、プロパティの一部を変更する可能性もあるクラスインスタンスを作成します。

各関数の使用例については、以下のセクションを参照してください。

文字列として表示

クラスインスタンスの読みやすい文字列を表示するには、toString()関数を明示的に呼び出すか、toString()を自動的に呼び出すprintln()print()などのprint関数を使用できます。

kotlin
data class User(val name: String, val id: Int)

fun main() {
    val user = User("Alex", 1)
    
    // 出力を読みやすくするために toString() 関数が自動的に使用されます
    println(user)            
    // User(name=Alex, id=1)
}

これは、デバッグやログの作成に特に役立ちます。

インスタンスの比較

データクラスのインスタンスを比較するには、等値演算子==を使用します。

kotlin
data class User(val name: String, val id: Int)

fun main() {
    val user = User("Alex", 1)
    val secondUser = User("Alex", 1)
    val thirdUser = User("Max", 2)

    // user を secondUser と比較します
    println("user == secondUser: ${user == secondUser}") 
    // user == secondUser: true
    
    // user を thirdUser と比較します
    println("user == thirdUser: ${user == thirdUser}")   
    // user == thirdUser: false
}

インスタンスのコピー

データクラスインスタンスの正確なコピーを作成するには、そのインスタンスでcopy()関数を呼び出します。

データクラスインスタンスのコピーを作成し、プロパティの一部を変更するには、そのインスタンスでcopy()関数を呼び出し、関数のパラメータとしてプロパティの置き換え値を追加します。

例:

kotlin
data class User(val name: String, val id: Int)

fun main() {
    val user = User("Alex", 1)

    // user の正確なコピーを作成します
    println(user.copy())       
    // User(name=Alex, id=1)

    // user のコピーを name: "Max" で作成します
    println(user.copy("Max"))  
    // User(name=Max, id=1)

    // user のコピーを id: 3 で作成します
    println(user.copy(id = 3)) 
    // User(name=Alex, id=3)
}

インスタンスのコピーを作成することは、元のインスタンスを変更するよりも安全です。なぜなら、元のインスタンスに依存するコードがコピーとその操作によって影響を受けないためです。

データクラスの詳細については、データクラスを参照してください。

このツアーの最後の章は、KotlinのNull安全性についてです。

練習

演習 1

名前と給与の2つのプロパティを持つデータクラスEmployeeを定義してください。給与のプロパティは可変であることを確認してください。そうしないと、年末に昇給が得られません!main関数はこのデータクラスの使用方法を示しています。

kotlin
// Write your code here

fun main() {
    val emp = Employee("Mary", 20)
    println(emp)
    emp.salary += 10
    println(emp)
}
解答例
kotlin
data class Employee(val name: String, var salary: Int)

fun main() {
    val emp = Employee("Mary", 20)
    println(emp)
    emp.salary += 10
    println(emp)
}
演習 2

このコードがコンパイルするために必要な追加のデータクラスを宣言してください。

kotlin
data class Person(val name: Name, val address: Address, val ownsAPet: Boolean = true)
// Write your code here
// data class Name(...)

fun main() {
    val person = Person(
        Name("John", "Smith"),
        Address("123 Fake Street", City("Springfield", "US")),
        ownsAPet = false
    )
}
解答例
kotlin
data class Person(val name: Name, val address: Address, val ownsAPet: Boolean = true)
data class Name(val first: String, val last: String)
data class Address(val street: String, val city: City)
data class City(val name: String, val countryCode: String)

fun main() {
    val person = Person(
        Name("John", "Smith"),
        Address("123 Fake Street", City("Springfield", "US")),
        ownsAPet = false
    )
}
演習 3

コードをテストするために、ランダムな従業員を作成できるジェネレーターが必要です。潜在的な名前の固定リスト(クラス本体内)を持つRandomEmployeeGeneratorクラスを定義してください。クラスを最小給与と最大給与(クラスヘッダー内)で設定してください。クラス本体内でgenerateEmployee()関数を定義してください。main関数がこのクラスの使用方法を再度示しています。

TIP

この演習では、Random.nextInt()関数を使用できるようにパッケージをインポートします。 パッケージのインポートの詳細については、パッケージとインポートを参照してください。

ヒント 1
リストには、リスト内のランダムな項目を返す.random()という拡張関数があります。
ヒント 2
Random.nextInt(from = ..., until = ...)は、指定された範囲内のランダムなInt数値を返します。
kotlin
import kotlin.random.Random

data class Employee(val name: String, var salary: Int)

// Write your code here

fun main() {
    val empGen = RandomEmployeeGenerator(10, 30)
    println(empGen.generateEmployee())
    println(empGen.generateEmployee())
    println(empGen.generateEmployee())
    empGen.minSalary = 50
    empGen.maxSalary = 100
    println(empGen.generateEmployee())
}
解答例
kotlin
import kotlin.random.Random

data class Employee(val name: String, var salary: Int)

class RandomEmployeeGenerator(var minSalary: Int, var maxSalary: Int) {
    val names = listOf("John", "Mary", "Ann", "Paul", "Jack", "Elizabeth")
    fun generateEmployee() =
        Employee(names.random(),
            Random.nextInt(from = minSalary, until = maxSalary))
}

fun main() {
    val empGen = RandomEmployeeGenerator(10, 30)
    println(empGen.generateEmployee())
    println(empGen.generateEmployee())
    println(empGen.generateEmployee())
    empGen.minSalary = 50
    empGen.maxSalary = 100
    println(empGen.generateEmployee())
}