Kotlin クラスとオブジェクト

クラスの定義

Kotlinクラスには、コンストラクタと初期化コードブロック、関数、属性、内部クラス、オブジェクト宣言を含めることができます。

Kotlinはキーワード classでクラスを宣言し、続いてクラス名を使用します。

class Ceodata {  // クラス名は Ceodata
    // 中括弧の中にはクラスの構成です
}

空白のクラスを定義できます。

class Empty

クラスにメンバー関数を定義できます。

class Ceodata() {
    fun zoo() { print("Zoo") } //メンバー関数
}

クラスの属性

属性の定義

クラスの属性はキーワードvarで可変に宣言できます。そうしないと、読み取り専用のキーワードvalは非可変として宣言されています。

class Ceodata {
    var name: String = ……
    var url: String = ……
    var city: String = ……
}

通常の関数を使用してコンストラクタを使用してクラスインスタンスを作成できます。

val site = Ceodata() // Kotlinにはキーワードnewがありません

属性を使用するには、名前でそれを参照すればいいです。

site.name           // . 記号で参照します
site.url

Koltinのクラスはデフォルトコンストラクタまたは1つ以上のセカンダリコンストラクタができ、主コンストラクタはクラスのヘッダーの一部で、クラス名の後にあります。

class Person constructor(firstName: String) {}

デフォルトコンストラクタにコメントまたは可視性修飾子がない場合、キーワードのconstructorを省略できます。

class Person(firstName: String) {
}

geeterとsetter

属性の宣言構文:

var <propertyName>[: <PropertyType>] [= <property_initializer>]
    [<getter>]
    [<setter>]

getterとsetterはオプションです

属性の型が初期化ステートメントまたはクラスのメンバー関数から推測できる場合、型を省略でき、valは読み取り専用のsetter関数を許可しません。

var allByDefault: Int? // エラー:初期化ステートメントが必要で、デフォルトでgetter と setterメソッドが実装されます。
var initialized = 1    // int型で、デフォルトでgetter と setterメソッドが実装されます。
val simple: Int?       // int型で、デフォルトでgetterメソッドが実装されますが、コンストラクタで初期化する必要があります。
val inferredType = 1   // int型で、デフォルトでgetterメソッドが実装されます。

実例

次の例では、2つの可変変数であるlastNameとnoが含むPersonクラスを定義します。lastNameがgetterメソッドを変更し、noがsetterメソッドを変更します。

class Person {

    var lastName: String = "tom"
        get() = field.toUpperCase()   // 変数を割り当てた後大文字に変換します
        set

    var no: Int = 100
        get() = field                // バックエンド(環境変数)
        set(value) {
            if (value < 10) {       // 値が10未満の場合、この値を返します
                field = value
            } else {
                field = -1         // 値が大なり10の場合、-1を返します
            }
        }


    var heiht: Float = 145.4f
        private set
}

// テスト
fun main(args: Array<String>) {
    var person: Person = Person()

    person.lastName = "florian"

    println("lastName:${person.lastName}")

    person.no = 9
    println("no:${person.no}")

    person.no = 20
    println("no:${person.no}")

}

出力結果は次のとおりです。

lastName:florian
no:9
no:-1

Kotlinにはフィールドを含むことができません。Backing Fields(環境変数) を提供し、スペアフィールドはfieldキーワードで宣言し、fieldキーワードは、上記の実例のように属性のアクセサにのみ使用できます。

var no: Int = 100
        get() = field                // Backing Fields(環境変数)
        set(value) {
            if (value < 10) {       // 値が10未満の場合、この値を返します
                field = value
            } else {
                field = -1         // 値が大なり10の場合、-1を返します
            }
        }

空白ではない属性を初期化する必要がある場合、KotLinは、LateInitキーワード記述属性で初期化を遅らせる方法を提供します。

public class MyTest {
    lateinit var subject: TestSubject

    @SetUp fun setup() {
        subject = TestSubject()
    }

    @Test fun test() {
        subject.method()  // dereference directly
    }
}

デフォルトコンストラクタ

デフォルトコンストラクタには任意のコードを含めることはできず、初期化コードを初期化コードセグメントに配置することができ、初期化コードセグメントはINITキーワードをプレフィックスとして使用します。

class Person constructor(firstName: String) {
    init {
        println("FirstName is $firstName")
    }
}

ヒント:デフォルトコンストラクタのパラメータは、初期化コードセグメント内、またはクラス本体nによって定義された属性初期化コードで使用できます。シンプルな構文については、デフォルトコンストラクタによって属性を定義し、属性値を初期化できます。(varまたはvalにすることができます)

class People(val firstName: String, val lastName: String) {
    //...
}

コンストラクタにコメントが付けられ、または可視修飾子がある場合は、constructorキーワードが必要で、コメントと修飾子はその前に配置されます。

実例

Ceodataクラスを作成し、コンストラクタをサイト名に渡します。

class Ceodata constructor(name: String) {  // クラス名は Ceodataです
    // 中括弧の中ではクラス構成です
    var url: String = "http://www.ceodata.com"
    var country: String = "JP"
    var siteName = name

    init {
        println("初期化ウェブサイト名: ${name}")
    }

    fun printTest() {
        println("クラスの関数です")
    }
}

fun main(args: Array<String>) {
    val ceodata =  Ceodata("初心者チュートリアル")
    println(ceodata.siteName)
    println(ceodata.url)
    println(ceodata.country)
    ceodata.printTest()
}

実行の結果:

初期化ウェブサイト名:初心者チュートリアル
初心者チュートリアル
http://www.ceodata.com
JP
クラスの関数です

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

クラスにセカンダリコンストラクタがあることもできます。プレフィックスconstructorを追加する必要があります。

class Person { 
    constructor(parent: Person) {
        parent.children.add(this) 
    }
}

クラスがデフォルトコンストラクタを含む場合、各セカンダリコンストラクタは必須で、または別のセカンダリコンストラクタによってデフォルトコンストラクタを変わります。同じクラスで別のセカンダリコンストラクタ関数にキーワードthisを使用します。

class Person(val name: String) {
    constructor (name: String, age:Int) : this(name) {
        // 初期化...
    }
}

非抽象クラスがコンストラクタ(デフォルトコンストラクタ或はセカンダリコンストラクタ)を宣言しない場合、パラメータなしでコンストラクタを作成します。コンストラクタはpublicです。 クラスにpublicコンストラクタ関数を必要としない場合は、空のデフォルトコンストラクタを宣言する必要があります。

class DontCreateMe private constructor () {
}

ヒント:JVM仮想マシンでは、デフォルトコンストラクタにあるすべてのパラメータがデフォルト値がある場合、コンパイラは追加のパラメータなしのコンストラクタを生成し、デフォルト値を直接使用します。 これより、Kotlinは、Jackson或はJPAのようなパラメータなしのコンストラクタを使用してクラスインスタンスのライブラリを作成できます。

class Customer(val customerName: String = "")

実例

class Ceodata constructor(name: String) {  // クラス名は Ceodataです
    // 中括弧の中ではクラス構成です
    var url: String = "http://www.ceodata.com"
    var country: String = "JP"
    var siteName = name

 init {
        println("初期化ウェブサイト名: ${name}")
    }
    // セカンダリコンストラクタ関数
    constructor (name: String, alexa: Int) : this(name) {
        println("Alexa の順位は $alexa"位です)
    }

    fun printTest() {
        println("クラスの関数です")
    }
}

fun main(args: Array<String>) {
    val ceoata =  Ceodata("初心者チュートリアル", 10000)
    println(ceodata.siteName)
    println(ceodata.url)
    println(ceodata.country)
    ceodata.printTest()
}

実行の結果:

初期化ウェブサイト名:初心者チュートリアル
Alexa の順位は 10000位です
初心者チュートリアル
http://www.ceodata.com
JP
クラスの関数です

抽象クラス

抽象クラスは、オブジェクト指向プログラミングの特徴の1つで、クラス自体、またはクラス内の一部のメンバーはabstractに宣言できます。抽象メンバーはクラスに具体的な実装が存在していません。

ヒント:抽象クラスや抽象メンバーにopenコメントをマークする必要はありません。

open class Base {
    open fun f() {}
}

abstract class Derived : Base() {
    override abstract fun f()
}

ネストしたクラス

他のクラスにクラスをネストできます。次には例を挙げます。

class Outer {                  // 外部クラス
    private val bar: Int = 1
    class Nested {             // ネストしたクラス
        fun foo() = 2
    }
}

fun main(args: Array<String>) {
    val demo = Outer.Nested().foo() // 呼び出し構文:外部クラス.ネストしたクラス.ネストメソッド/プロパティ
    println(demo)    // == 2
}

内部クラス

内部クラスはキーワードinnerを使用して表されます。

内部クラスは外部クラスオブジェクトへの参照があり、内部クラスは外部クラスメンバー属性とメンバー関数にアクセスできます。

class Outer {
    private val bar: Int = 1
    var v = "メンバー属性"
    /**ネストした型-内部クラス**/
    inner class Inner {
        fun foo() = bar  // 外部クラスメンバーにアクセスします
        fun innerTest() {
            var o = this@Outer //外部クラスのメンバー変数を取得します
            println("内部クラスは、外部クラスのメンバーを参照できます。例えば:" + o.v)
        }
    }
}

fun main(args: Array<String>) {
    val demo = Outer().Inner().foo()
    println(demo) //   1
    val demo2 = Outer().Inner().innerTest()   
    println(demo2)   // 内部クラスは、外部クラスのメンバーを参照できます。例えば:メンバー属性
}

曖昧さを排除するためには、外部範囲の thisにアクセスする場合、this@labelを使用します。@labelはthisのソースを指すタグです。

匿名内部クラス

Object式を使用して、匿名内部クラスを作成します。

class Test {
    var v = "メンバー属性"

    fun setInterFace(test: TestInterFace) {
        test.test()
    }
}

/**
 * インターフェイスを定義します
 */
interface TestInterFace {
    fun test()
}

fun main(args: Array<String>) {
    var test = Test()

    /**
     * Object式によって、インターフェイスオブジェクト、つまり匿名内部クラスを作成する例です。
     */
    test.setInterFace(object : TestInterFace {
        override fun test() {
            println("Object式で匿名内部クラスを作成する例です。")
        }
    })
}

クラス修飾子

クラス修飾子には、ClassModifierと_accessModifier_が含まれます。

classModifier: クラス属性修飾子、クラスの特性を表示します。
abstract // 抽象クラス
final // クラスは継承できません。デフォルト属性です
enum // 列挙型
open // クラスは継承でき、クラスのデフォルトはfinalです
annotation // アノテーション

accessModifier: アクセス修飾子


private // 同じファイル内でのみ表示します
protected // 同じファイルまたはサブクラス内に表示します
public // すべての参照したところが表示します
internal // 同じモジュールに表示します

実例

// ファイル名:example.kt
package foo

private fun foo() {} // example.kt内に表示します

public var bar: Int = 5 // このプロパティは表示しています

internal val baz = 6    // 同じモジュールに表示します
Share

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です