【KotlinとJava】Data型の自動関数宣言

KotlinとJava

データ型を宣言すると、暗黙的にいくつかの関数を利用することができる。Javaでは手作業で作っていたものがライブラリなしで使うことができるのだ。

Autogenerated functions.kt

data class User(val name: String, val id: Int)

fun main(args: Array<String>) {
    val user = User("Alex", 1)
    println(user) // toString()

    val secondUser = User("Alex", 1)
    val thirdUser = User("Max", 2)

    println("user == secondUser: ${user == secondUser}")
    println("user == thirdUser: ${user == thirdUser}")

    // copy() function
    println(user.copy())
    println(user.copy("Max"))
    println(user.copy(id = 2))
    println(user.copy("Max", 2))
}

リンク

toString

実行するとメンバー変数の内容を以下のように展開してくれる。

User(name=Alex, id=1)

JavaではtoStringをオーバーライドして作りこむ必要があったので、とても便利。

operator “==”

当たり前のようにクラスを==で比較しているが、これはJavaでは行えない芸当だ。

また、後述の「Javaで記述」ではequalsメソッドで代用しているが、実はそれでも足りない。上記コードの実行結果では一つ目の比較はなんとtrue、二つ目の比較はfalseとなる。
Javaはオブジェクトの比較はオブジェクトが格納されているアドレスを比較するため、メンバー変数を比較するためにはequalsメソッドのオーバーライドが必要なのだ。

Kotlinはこんなことをこともなげに行ってくれる。

copy

元のインスタンスをコピーして、新しいインスタンスを得るという機能だが、Kotlinは一部のメンバー変数の書き換えもサポートしてくれる。

しかも、変数名を指定することができるため、より柔軟に記述することができる。メンバー変数が10以上あるクラスを考えてみてほしい。そのクラスの5番目の変数だけ変更して新しいインスタンスが欲しいなどというときはぞっとしないだろうか?

Javaで記述

対比ができるようにJavaでも同じものを記述してみよう。

public class User {  
    private final String name;  
    private final int id;  
  
    public User(String name, int id) {  
        this.name = name;  
        this.id = id;  
    }  
  
    public String getName() {  
        return name;  
    }  
    public int getId() {  
        return id;  
    }  
  
    public User copy() {  
        return new User(this.name, this.id);  
    }  
    public User copy(String name) {  
        return new User(name, this.id);  
    }  
    public User copy(int id) {  
        return new User(this.name, id);  
    }  
    public User copy(String name, int id) {  
        return new User(name, id);  
    }  
  
    public String toString() {  
        String template = "User(name=%s, id=%d)";  
        return String.format(template, name, id);  
    }  
  
    @Override  
    public boolean equals(Object o) {  
        User u = (User)o;  
        // チェック手抜き  
        if (!(this.name.equals(u.name))) {  
            return false;  
        }  
        if (this.id != u.id) {  
            return false;  
        }  
        return true;  
    }  
}
public class Exp16 {  
    public static void main(String[] args) {  
        final User user = new User("Alex", 1);  
        System.out.println(user);  
  
        final User secondUser = new User("Alex", 1);  
        final User thirdUser = new User("Max", 2);  
  
        System.out.println("user.equals(secondUser)" + user.equals(secondUser));  
        System.out.println("user.equals(thirdUser)" + user.equals(thirdUser));  
  
        System.out.println(user.copy());  
        System.out.println(user.copy("Max"));  
        System.out.println(user.copy(2));  
        System.out.println(user.copy("Max", 2));  
    }  
}

Kotlinと同じ機能のクラスにするためには多くのコーディング追加が必要なことが分かる。toString, copy, equalsを記述していることに気が付くだろうか?

コメント

このブログの人気の投稿

【KotlinとJava】分解宣言

wxPythonでのモーダルダイアログ作成