Kotlinクラス – Kotlinコンストラクタ

このチュートリアルでは、Kotlinのオブジェクト指向プログラミングの概念について説明します。Kotlinのクラスについて詳しく説明します。また、Kotlinのコンストラクタ、アクセス修飾子、抽象クラスについても見ていきます。

Kotlinのクラス

クラスは、関数やプロパティをグループ化する定義であり、Kotlinではキーワードclassの後にクラス名が続きます。本体は中括弧の内側に記述されます。

class FirstClass {
}

クラスのインスタンスは、次のように生成されます:

val firstClass =  FirstClass()
var new = FirstClass() //here new is the name of the var.

Javaとは異なり、Kotlinではnewはキーワードではありません。Kotlinでは、クラスはデフォルトでfinalです。したがって、Javaでの上記の定義の相当する部分は次のようになります:

public final class FirstClass {
}

したがって、Kotlinではデフォルトでクラスは継承できません。クラスを非finalにするには、キーワードopenを追加する必要があります。

open class Me{
}

openアノテーションは、他のクラスがこのクラスを継承できるようにします。

Kotlinのクラスの例

クラスを作成して、いくつかの関数とプロパティを持たせましょう。そのクラスの関数とプロパティにどのようにアクセスするかを見てみましょう。さらに、メンバープロパティを設定する方法も見てみましょう。

class User {

    var loggedIn: Boolean = false
    val cantChangeValue = "Hi"
    
    fun logOn() {
        loggedIn = true
    }
    
    fun logOff() {
        loggedIn = false
    }
}

fun main(args: Array<String>) {

    val user = User()
    println(user.loggedIn) //false
    user.logOn()
    println(user.loggedIn) //true
    user.logOff()
    println(user.loggedIn) //false
    user.cantChangeValue = "Hey" //won't compile. Can't modify a final variable.

}

関数mainTest.ktクラスに属しています。メンバーと関数にアクセスするには、ドット演算子を使用する必要があります。valプロパティは、ドット演算子を使用して再設定することはできません。

Kotlin init

Kotlinの初期化ブロックは、以下に示すように定義されています。

class User {
    
    init{
        print("Class instance is initialised.")
    }

    var loggedIn: Boolean = false
    val cantChangeValue = "Hi"

    fun logOn() {
        loggedIn = true
    }

    fun logOff() {
        loggedIn = false
    }
}

initブロック内のコードは、クラスがインスタンス化されるときに最初に実行されます。 initブロックは、次に示すように任意の種類のコンストラクタでクラスがインスタンス化されるたびに実行されます。 クラス内に複数の初期化ブロックを記述できます。 これらは、次に示すように順次実行されます。

class MultiInit(name: String) {

    init {
        println("First initializer block that prints ${name}")
    }

    init {
        println("Second initializer block that prints ${name.length}")
    }
}

fun main(args: Array) {
    var multiInit = MultiInit("Kotlin")
}

//以下がログコンソールに出力されます。
//Kotlinを出力する最初のイニシャライザーブロック
//6を出力する2番目のイニシャライザーブロック

Kotlinのクラスでは、also関数を使用して、宣言自体でプロパティを出力することができます。 以下に示すように。

class MultiInit(name: String) {
    val firstProperty = "First property: $name".also(::println)

    init {
        println("First initializer block that prints ${name}")
    }

    val secondProperty = "Second property: ${name.length}".also(::println)

    init {
        println("Second initializer block that prints ${name.length}")
    }
}

fun main(args: Array) {

    var multiInit = MultiInit("Kotlin")
}

//以下が出力されます。
//最初のプロパティ:Kotlin
//Kotlinを出力する最初のイニシャライザーブロック
//2番目のプロパティ:6
//6を出力する2番目のイニシャライザーブロック

Kotlinコンストラクタ

Kotlinのコンストラクタは、プロパティを初期化するために使用される特別なメンバー関数です。Kotlinのコンストラクタは、Javaとは異なる方法で書かれ、構造化されています。デフォルトでは、以下に示すようにクラスには空のコンストラクタがあります:

class Student {
    var name: String
    val age : Int

    init {
        name = "Anupam"
        age = 24
    }

    init {
        name = "Anupam Chugh"
        //age = 26
    }
}

fun main(args: Array) {
    
    val student = Student()
    println("${student.name} age is ${student.age}")
    student.name = "Your"
    //student.age = 26 //コンパイルされません。ageはvalです
    println("${student.name} age is ${student.age}")

}

//以下がコンソールに表示されます:
//Anupam Chugh age is 24
//Your age is 24

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

Kotlinのプライマリコンストラクタは、以下に示すようにクラスヘッダー自体で定義されます。

class User(var name: String, var isAdmin: Boolean) {

    init {
        name = name + " @ JournalDev.com"
        println("Author Name is $name. Is Admin? $isAdmin")
    }
}

プライマリコンストラクタの定義はクラスヘッダー内に配置されます。注意: var として指定されていない限り、デフォルトでは、コンストラクタ引数は val です。

class User(name: String, isAdmin: Boolean)

上記のコードでは、nameとisAdminの両方を再代入することはできません。代わりに、以下に示すようにクラス内のメンバープロパティにコンストラクタ引数を割り当てることもできます。

class User(name: String, val isAdmin: Boolean) {

    var username  = name
    val _isAdmin = isAdmin

    init {
        username= username + " @ JournalDev.com"
        println("Author Name is $name. Is Admin? $_isAdmin")
    }
}

fun main(args: Array) {

    var user = User("Anupam",false)
    user.isAdmin = true //won't compile since isAdmin is val
    user._isAdmin = true //won't compile. Same reason.
    user = User("Pankaj",true)
}

//ログコンソールに以下が表示されます。
//Author Name is Anupam. Is Admin? false
//Author Name is Pankaj. Is Admin? true

Kotlinのコンストラクタデフォルト値

Kotlinでは、以下に示すように、コンストラクタ自体でデフォルト値を指定することができます。

class User(name: String, var website: String = "JournalDev") {

    init {
        println("Author $name writes at $website")
    }

    init {
        website = website + ".com"
        println("Author $name writes at $website")
    }
}

fun main(args: Array) {

    var user = User("Anupam","JournalDev")
    user = User("Pankaj","JournalDev")
}

//以下がコンソールに表示されます:
//著者アヌパムはJournalDevで執筆しています
//著者アヌパムはJournalDevで執筆しています.com
//著者パンカジはJournalDevで執筆しています
//著者パンカジはJournalDevで執筆しています.com

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

セカンダリコンストラクタは、キーワードconstructorを前置してクラスの本体に記述されます。次の例が同じことを示しています。

class Student {
    var name: String
    val age : Int

    constructor(name: String, age: Int)
    {
        this.name = name
        this.age = age
    }

    fun printDetails()
    {
        println("Name is $name and Age is $age")
    }

}

fun main(args: Array) {

    var student = Student("Anupam", 24)
    student.printDetails()
}

//以下がコンソールに印刷されます。
//名前はアヌパムで、年齢は24歳です

セカンダリコンストラクタの最も一般的な使用法は、サブクラスで、クラスを異なる方法で初期化する必要がある場合です。クラスにプライマリコンストラクタが含まれている場合、セカンダリコンストラクタはその宣言でそれを参照する必要があります。宣言はthisキーワードを使用して行われます。

class Student(var name: String, val age: Int) {

    var skill: String

    init {
        skill = "NA"
    }

    constructor(name: String, age: Int, skill: String) : this(name, age) {
        this.skill = skill
    }

    fun printDetails() {
        if (skill.equals("NA"))
            println("Name is $name and Age is $age")
        else
            println("Name is $name and Age is $age Skill is $skill")
    }
}

//以下がログコンソールに印刷されます:
//名前はアヌパムで、年齢は24歳です
//名前はアヌパムで、年齢は24歳です Skill is Kotlin

initブロックはメンバープロパティskillを初期化するために使用されます。セカンダリコンストラクタは: thisを使用してプライマリコンストラクタに委任しています。

カスタムのゲッターとセッター

これまでクラスのプロパティにはクラスのインスタンスにドット演算子を使用してアクセスし、変更してきました。アクセスをカスタマイズするためにsetおよびget構文を使用してみましょう。

class Name{
    var post: String = "default"
    set(value) {if(!post.isNotEmpty()) {
        throw IllegalArgumentException(" Enter a valid name")
    }
                field = value
                print(value)
    }

}

fun main(args: Array<String>) {

    var name = Name()
    name.post = "Kotlin Classes"
    name.post = ""
    name.post = "Kotlin Data Classes Our Next Tutorial"


}

以下がログコンソールに表示されます:

Kotlin Classes

Exception in thread "main" java.lang.IllegalArgumentException:  Enter a valid name
	at Name.setPost(Test.kt:16)
	at TestKt.main(Test.kt:78)

セッター内のfield変数は以前の値を保存します。ゲッターを追加しましょう。

class Name{
    var post: String = "default"
    set(value) {if(!post.isNotEmpty()) {
        throw IllegalArgumentException(" Enter a valid name")
    }
                field = value
    }
    get() {
        return field.capitalize()
    }

}

fun main(args: Array) {

    var name = Name()
    name.post = "kotlin classes"
    println(name.post)
    name.post = "kotlin data Classes our next Tutorial"
    println(name.post)

}

//以下が表示されます:
//Kotlinクラス
//Kotlinデータクラスは次のチュートリアル

capitalize()は文字列の最初の文字を大文字にします。注意: プロパティがvalである場合、setメソッドはコンパイルされません。

Kotlinの可視性修飾子

  • Public:この修飾子を持つクラス、関数、プロパティ、インターフェース、またはオブジェクトは可視で、どこからでもアクセスできます。
  • プライベート: この修飾子で定義されたクラス/関数は、同じファイル内からのみアクセスできます。 この修飾子を持つクラス/関数のメンバー/プロパティは、そのブロック内からのみアクセスできます。
  • 保護された:この修飾子は、同じくプライベートと同じですが、サブクラス内での可視性とアクセスを許可します。
  • 内部:この修飾子を持つクラス/インターフェース/関数は、同じモジュール内でのみアクセスできます。

可視性修飾子は、コンストラクタにも適用されます。プライマリコンストラクタに修飾子を割り当てるには、クラスヘッダー内のコンストラクタとともにキーワードconstructorを指定する必要があります。

class Student private constructor (var name: String, val age: Int) {

    var skill: String

    init {
        skill = "NA"
    }

    constructor(name: String, age: Int, skill: String) : this(name, age) {
        this.skill = skill
    }

    fun printDetails() {
        if (skill.equals("NA"))
            println("Name is $name and Age is $age")
        else
            println("Name is $name and Age is $age Skill is $skill")
    }
}

fun main(args: Array) {

    var student = Student("Anupam",24,"Kotlin")
    student.printDetails()
}

//prints
//名前はアヌパムで、年齢は24、スキルはKotlin

プライベートコンストラクタはクラスの外部から呼び出すことはできません。 上記のコードでは、セカンダリコンストラクタを使用してのみ、異なる関数内でクラスのインスタンス化ができます。

Kotlin抽象クラス

Javaと同様に、Kotlinでは抽象クラスを宣言するためにabstractキーワードが使用されます。 抽象クラスはインスタンス化できませんが、サブクラスによって継承されることができます。 デフォルトでは、抽象クラスのメンバーは非抽象ですが、それ以外が記述されていない限り。

abstract class Person(name: String) {

    init {
        println("Abstract Class. init block. Person name is $name")
    }

    abstract fun displayAge()
}

class Teacher(name: String): Person(name) {

    var age : Int

    init {
        age = 24
    }

    override fun displayAge() {
        println("Non-abstract class displayAge function overridden. Age is $age")
    }
}

fun main(args: Array) {

    val person = Teacher("Anupam")
    person.displayAge()

}

//以下がコンソールに出力されます。
//抽象クラス。 初期化ブロック。 人の名前はアヌパム
//非抽象クラス。 年齢は24

注意: 抽象クラスはデフォルトでopenです。したがって、サブクラス化を許可するためにopen修飾子を追加する必要はありません。overrideキーワードは、サブクラスでメソッドをオーバーライドするために使用されます。このチュートリアルでは、Kotlinのクラスの基本をカバーしました。データクラス、シールドクラス、継承など、まだたくさんあります。これらについては、今後のチュートリアルでカバーします。参考文献:Kotlinドキュメント

Source:
https://www.digitalocean.com/community/tutorials/kotlin-class-constructor