Kotlin入門:クラス

#クラス

構文

```Kotlin
class name(){
    definition
}
```

`name`:クラス名
`definition`:クラスの中身

入力例

```Kotlin
①class Person(){
      fun sayHello(){
          println("Hello")
      }
  }
  fun main() {
②    val person = Person()
      person.sayHello()
  }
```

実行結果は以下の通りです。

```Kotlin
Hello
```

①ではクラス名の後方に()があることに注意。
これはコンストラクターの引数を表すカッコです。

②ではインスタンス化していますが、`new`演算子は不要です。

##アクセス修飾子

`public`:すべてのクラスからアクセス可能、既定のアクセス修飾子
`protected`:現在のクラスとそのサブクラスからのみアクセス可能
`internal`:同じモジュール内のクラスからのみアクセス可能
`private`:現在のクラスからのみアクセス可能

##プロパティ

アクセサーを伴うプロパティの構文

構文

```Kotlin
var name :type = init
getter
setter
```

`name`:プロパティ名
`type`:データ型
`init`:初期値
`getter`:ゲッター
`setter`:セッター

以下は入力例です。

```Kotlin
class Person(){
    var name = "山田"
    var age = 20
        set(value){
①    	    field = value
	    }
    fun show(){
        println("名前は${name}です。年齢は${age}歳です。")
    }
}
fun main() {    
    val person = Person()
    person.age = 30
    person.show()
}
```
①`field`はバッキングフィールドと言います。
バッキングフィールドとは、プロパティ値を格納するために
裏側で自動生成されるフィールドのことです。

実行結果は以下の通りです。

```Kotlin
名前は山田です。年齢は30歳です。
```

以下の通り、`setter`や`getter`は省略することもできます。

```Kotlin
class Person(){
    var name = "山田"
    var age = 20
	fun show(){
        println("名前は${name}です。年齢は${age}歳です。")
    }
}
fun main() {    
    val person = Person()
    person.age = 30
    person.show()
}
```

プロパティ名が`var`命令で宣言されているということに注意！

##読み取り専用のプロパティ

val命令を使用すると読み取り専用のプロパティとすることができます。

```Kotlin
class Person(){
    val name = "山田"
    var age = 20
    fun show(){
        println("名前は${name}です。年齢は${age}歳です。")
    }
}
fun main() {    
    val person = Person()
①  person.name = "鈴木"
    person.show()
}
```

①でエラーが発生します。
`getter`の設定はできますが、`setter`の設定はできません。

###private set
クラス外からのみ読み取り専用にしたい場合に`private setter`を使用します。

```Kotlin
class Person(){
    val name = "山田"
    var age = 20
①   	private set
    fun show(){
        println("名前は${name}です。年齢は${age}歳です。")
    }
}
fun main() {    
    val person = Person()
②  person.age = 25
    person.show()
}
```

①はアクセス権限のみを変更したい場合の書き方です。
`setter`には既定の実装が適用されます。

②でエラーが発生します。クラス内からではなく、クラス外からアクセスしようとしたためです。

アクセス修飾子を変更できるのは`setter`のみです。


##コンストラクター
コンストラクターには２種類あります。
**プライマリコンストラクター**と**セカンダリコンストラクター**です。

まず１つ目のコンストラクターはプライマリコンストラクターとして扱い、
２つ目以降はセカンダリコンストラクターとして扱います。

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

プライマリコンストラクターは、
クラスに１つだけ記述できるコンストラクターで、
classブロックの一部として表します。

```Kotlin
class Person(name:String,age:Int){
    var name:String
    var age:Int
    init{
①      this.name = name
        this.age = age
    }
    fun show(){
        println("名前は${this.name}です。年齢は${this.age}歳です。")
    }
}
fun main() {    
    val person = Person("鈴木",25)
    person.show()
}
```

①のような初期化コードを省略して以下のような書き方ができます。
以下でのポイントはクラスの引数にvar命令を用いていることです(valでも可)。

```Kotlin
class Person(var name:String,var age:Int){
    fun show(){
        println("名前は${this.name}です。年齢は${this.age}歳です。")
    }
}
fun main() {    
    val person = Person("鈴木",25)
    person.show()
}
```

引数に`var`または`val`命令を使用することで引数がプロパティ宣言とみなされます。


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

１つのクラスに２個以上のコンストラクターがある場合、
以降はセカンダリコンストラクターとして扱います。

```Kotlin
class Person(var name:String, var age:Int){
①  constructor(age:Int):this("鈴木",age){}
②  constructor():this(15){}
    fun show(){
        println("名前は${this.name}です。年齢は${this.age}歳です。")
    }
}
fun main() {    
    val person = Person()
    person.show()
}
```

①１つ目のセカンダリコンストラクターで引数`name`を省略しています。
②２つ目のセカンダリコンストラクターで引数`name`と`age`を省略しています。

セカンダリコンストラクターは`constructor`ブロックで定義します。
後方の`:this()`は他のコンストラクターを呼び出すための構文です。

プライマリコンストラクターが存在する場合、
セカンダリコンストラクターは最終的に必ずプライマリコンストラクターを呼び出さなければなりません。
上記のコードでコンストラクターが呼ばれる順番は
①→②→プライマリコンストラクター　です。