日々常々

ふつうのプログラマがあたりまえにしたいこと。

JavaSE8でinterfaceにstaticメソッドを持てるようになったので

Javaの古きアレなプラクティスの1つに、ユーティリティクラス*1をabstractで作成すると言うのがある。

public abstract class SomeUtil {
    public static String appendA(String str) {
        return str + "a";
    }
}

ユーティリティメソッドappendAは、特に役に立たないが、引数のStringにAを足して返す物体だ。このクラスにはstaticメソッドしか含まないため、インスタンス化する必要はない。こういうクラスをabstractにすることにより、誤ってインスタンス化されることは無いと言う素晴らしい方法である。

「ねーよ」と言う言葉は堪えて頂きたい。それでは話が終わってしまう。


さて、JavaSE8ではProject Lambdaのついでにインタフェースにdefaultメソッドが追加された。ついでにstaticメソッドも書けるようになった。なぜstaticも書けるようになったかは知らない。

今までabstractなユーティリティクラスを書いていた人に朗報だ。これからはinterfaceに書けば良い。"abstract class"と記述していたのが"interface"で良くなる。14文字から9文字になる。なんと生産性が150%になる。素晴らしい。

いやまて、interfaceに記述できると言うことは、古きアレなプラクティスの1つ、インタフェースにstatic名前付き定数を定義してimportすることにより、クラスで使用するときに修飾しなくて良くなると言うものがある。*2 *3

staticメソッドでもこれは使えるのでは……こう!!

public class Main implements ISomeUtil {
    public static void main(String... args) {
        System.out.println(hello());
    }
}

interface ISomeUtil {
    public static String hello() { 
        return "HELLO";
    }
}

即座にコンパイル

% javac Main.java 
Main.java:3: エラー: シンボルを見つけられません
        System.out.println(hello());
                           ^
  シンボル:   メソッド hello()
  場所: クラス Main
エラー1個

……(´・ω・`)


なんかちゃんと"ISomeUtil.hello()"とか指定しないと呼べないみたい。staticフィールドはいいのに。
まあできても嬉しく無いので、できなくていいけど。


関係しそうでしないdefaultメソッドのDiamond継承について昔かいたやつ → DiamondProblemの対応で気になったこと - 日々常々

*1:ここではstaticメソッドのみを定義したクラスをユーティリティクラスと言ってたりする

*2:interfaceは複数implementsできるため、これを行っても何かを損なうわけではない。

*3:static importの導入で、よりアレさが増したもの。