【val?var?】KotlinのプロパティのJavaからの見え方【isEnabledの名前は?】

# はじめに

本投稿ではJavaとKotlinの相互運用において、

「Kotlinのクラスで定義したプロパティが、Javaからどのように見えるのか、呼び出すことができるのか」

を紹介します。まず

* Getterのみ
* SetterとSetterの両方

が生成される場合があることを説明し、次に生成されるSetterとGetterの名前について説明します。

# Getterのみができるのか？GetterとSetter両方ができるのか？

次のようなKotlinのPersonクラスを用意します。

```kotlin:Personクラス
class Person(val name:String, var age:Int)
```

Kotlinでの利用例はこんな感じですね

* valで定義したnameは書き換えることができません。値or参照の取得のみが可能です。
* varで定義したageは書き換えることができます。値or参照の取得・設定両方が可能です。

```kotlin:PersonクラスのKotlinでの利用例
val person = Person("Ryota", 27)
println(person.name)
println(person.age)

// 下記はコンパイルエラー
// person.name = "RyotaMurohoshi"
person.age = 28

println(person.name)
println(person.age)
```

さて、このPersonクラスをJavaから使った場合どのように利用できるでしょうか？Javaでの利用例を下記に示します。

```java:
Person person = new Person("Ryota", 27);
System.out.println(person.getName());
System.out.println(person.getAge());

// 下記はコンパイルエラー
// person.setName("Super Ryota");
person.setAge(28);

System.out.println(person.getName());
System.out.println(person.getAge());
```

* valで定義したnameはGetterのみが利用できました。getNameメソッドですね。
* varで定義したageはGetterとSetter両方が利用できました。getAgeメソッド、setAgeメソッドですね。


まとめると

* valで定義したプロパティは、JavaではGetterのみが作られ利用できる
* varで定義したプロパティは、JavaではGetterとSetterが作られ両方が利用できる

ですね。



# どのような名前のGetter・Setterが作られるのか

ではどのような名前のGetterとSetterが生成されるのでしょう？

## 原則

先ほどのKotlinのageというプロパティは、

* GetterはgetAge
* SetterはsetAge

が生成されました。

原則のルールは次のとおりです。

xxxという名前のプロパティは

* getXxx
* setXxx

というアクセサが生成されます。ただしvalの場合はSetterは生成されません。

## isXxxというKotlinのプロパティ

KotlinではBoolean型のプロパティにisXxxという名前を使うと思います。さて、これが先ほどの原則ルールに適用されたとします。Javaからはどう利用できるでしょうか。もし、先ほどの原則ルールに則るならば、

isXxxというプロパテには

* getIsXxx
* setIsXxx

というような形になるのでしょうか？不自然なGetterとSetterですね。

では、実際のコードで見てみましょう。次のようにisXxxという名前のプロパティがあるクラスを作ります。

```kotlin:KotlinのKData0クラス
class KData0(var isEnabled:Boolean, var isValid:String)
```

このKotlinのクラスをJavaから使ってみます。

```Java:KData0クラスをJavaから利用する
KData0 kData0 = new KData0(true, "xxxxx");            

System.out.println(kData0.isEnabled());
System.out.println(kData0.isValid(););

kData0.setEnabled(true);
kData0.setValid("fffff");
```


isEnabledというプロパティでは、

* isEnabledというGetter
* setEnabledというSetter

ができました。

isValidというプロパティでは、

* isValidというGetter
* setValidというSetter

ができました。

まとめると、ixXxxというプロパティは、

* isXxxというGetter
* setXxxというSetter

ができます。

まとめると、isXxxというプロパティは原則ルールと違うルールが適用され、Javaとして自然なGetter・Setterが生成されます。

ちなみに、Boolean型以外でisXxxというプロパティ名は利用しないと思います。しかし、isXxxというプロパティはBoolean型以外でもこのルールでGetter・Setterが生成されます。

# is_xxxというKotlinのプロパティ

Java・Kotlinの命名規則としては正しくはないかもしれませんが、is_xxxという名称のプロパティはどのようにJavaから利用できるでしょうか。

```kotlin:KotlinのKData0クラス
class KData1(var is_enabled:Boolean, var is_valid:String)
```

このKotlinのクラスをJavaから使ってみます。

```Java:KData1クラスをJavaから利用する
KData1 kData1 = new KData1(true, "xxxxx");

System.out.println(kData1.is_valid(););
System.out.println(kData1.is_enabled());

kData1.set_enabled(true);
kData1.set_valid("fffff");
```

is_enabledというプロパティでは、

* is_enabledというGetter
* set_enabledというSetter

ができました。

is_validというプロパティでは、

* is_validというGetter
* set_validというSetter

ができました。

まとめると、ix_xxxというプロパティは、

* is_xxxというGetter
* set_xxxというSetter

これも、Boolean型以外のis_xxxというプロパティ名でもこのルールが適用されます。

## その他は？

hasXxxというプロパティはどうでしょうか？


これは、

* getHasXxx
* setHasXxx

という原則ルールが適用されるようです。

そしてisxxxというプロパティは

* getIsxxx
* setIsxxx

と、こちらも原則ルールが適用されるようです。

どうやら、プロパティ名がキャメルケース・スネークケースで区切られていて先頭がisの場合に、例外ルールが適用されるようですね。


# さいごに

KotlinはJavaとの連携を非常に大事にしています。
この投稿では、Kotlinで作ったクラスのプロパティが、JavaからはGetter・Setterとして利用できるのですが、そのルールと例を紹介しました。

Kotlinのクラスのvarで作ったプロパティは、JavaからはGetter・Setterの両方が利用できます。
Kotlinのクラスのvalで作ったプロパティは、JavaからはGetterのみが利用できます。

また、Kotlinのクラスのxxxという名前のプロパティはJavaからはgetXxxやsetXxxというアクセサが利用できます。(setXxxはvarのみ)
一方で、KotlinのクラスのisXxxという名前のプロパティはJavaからはisXxxやsetXxxというアクセサが利用できます。(setXxxはvarのみ)


さて最後に問題です。

```kotlin:
class Data(var isXxx:String, var xxx:String)
```

というクラスはコンパイルエラーになります。理由はなんでしょうか？

このクラスをJavaから見たとき、どのようなアクセサが利用できるか考えてください。

isXxxプロパティは

* isXxx
* setXxx

ですね。

xxxプロパティは

* getXxx
* setXxx

ですね。

setXxxという名前が衝突しているため、コンパイルエラーになるのです。

さてこの投稿とは逆に、JavaのアクセサをKotlinからプロパティ形式で利用できます。それはまた、別の機会で。

参考コードは、[こちら](https://github.com/RyotaMurohoshi/memos/tree/04144ad3444094b9a97c97604c5d78ee1ec76187/code_snippets/jvms/is_property_example)。

# 関連

[【Kotlin】BooleanフィールドはisXXXという命名が推奨されている
](http://yyyank.blogspot.jp/2016/01/kotlinbooleanisxxx.html#Pa3T84S.twitter_tweet_box_count)