読者です 読者をやめる 読者になる 読者になる

KotlinのInterfaceはPropertyも定義できるんだよ

そういえば最近は仕事でもKotlinを書いています。同僚をKotlinで洗脳した甲斐があるというものです。 developers.eure.jp

しかし、全員が全員Javaを書く際と同じようにすらすらKotlinを書くことができるわけではないので、私がKotlinのTipsや文法などをつぶやくSlackのチャンネルがあり、みんなにはそれ読んでもらっています。 せっかくなのでこれからは自分のブログにも転載していこうと思います。 多少雑です。

tl;dr

  • KotlinのInterfaceはデフォルト実装を定義できる
  • KotlinのInterfaceは(バッキングフィールドを持たないものであれば)プロパティを定義できる

そういえば、(1.1からはできるが)data classは継承をサポートしてないので、デフォルト実装やpropertyをもつinterfaceを実装することで、なにかしら有効活用できそうですね。

KotlinのInterface

デフォルト実装を定義できる。

KotlinのInterfaceはJava8のInterfaceと同様に、デフォルト実装を定義できます。

interface Foo {
    fun doSomething() = "default"
}

class FooImpl : Foo {
    
}

// -------------------

val foo = FooImpl()
foo.doSomething() // return "default"

Propertyを定義できる。

JavaではInterfaceにフィールドを定義することはできませんでした。
しかし、KotlinではBacking fieldを持たないPropertyであれば定義する事ができます。

interface Foo {
    val one: Int
}

class FooImpl : Foo {
    override val one = 2
}

Backing Fieldとは

うまく説明できる気がしないのでKotlinコードと、そこから生成されるByteCodeをJavaデコンパイルしたものの対比をみて察してください。
Javaコード側でfieldの定義されているA, C, Eをbacking fieldを持ったpropertyといいます。

あわせて読みたい:

13日目:プロパティとフィールド - Kotlin Advent Calendar 2012 (全部俺)

case A

class Kotlin {
    val a = 2
}

public final class Java {
    private final int a = 2;

    public final int getA() {
       return this.a;
    }
}

case B

class Kotlin {
    val b: Int
        get() = 2
}

public final class Java {
    public final int getB() {
       return 2;
    }        
}

case C

class Kotlin {
    var c = 2
}

public final class Java {
   private int c = 2;

   public final int getC() {
      return this.c;
   }

   public final void setC(int <set-?>) {
      this.c = <set-?>;
   }
}

case D

class Kotlin {
    var d: Int
        get() = 2
        set(value) { }
}

public final class Java {
    public final int getD() {
       return 2;
    }
    
    public final void setD(int value) {
    }
}

case E

class Kotlin {
    var e: Int = 2
        set(value) { }
}

public final class Java {
   private int e = 2;

   public final int getE() {
      return this.e;
   }

   public final void setE(int value) {
   }
}