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

プログラムdeタマゴ

nodamushiの著作物は、文章、画像、プログラムにかかわらず全てUnlicenseです

パッケージ外では実装できないインターフェースがあったらなぁ

インターフェースが無修飾関数を宣言できない点はJAVAのいけてない点の一つだと思っている。


もちろん、インターフェースは宣言された関数が実装されていることを保証するための物だから、そのインターフェースで宣言された関数は全てに見えなくてはならない。故にpublicになるのは理論的に仕方のないことなのだ。


だが、外部からは触らせたくないけど、一つのインターフェースに宣言しておいた方が型変換などしなくて良くて便利な関数というのは多々あると思う。

こういった関数をうまく宣言する手段がない。


仮に、今ここでAというパブリックなインターフェースを定義し、パッケージ内でアクセス可能なBというAを拡張したインターフェースを定義したとする。
これで目的を達したように見えるが、Aインターフェースを公開しBを隠蔽している以上、Bインスタンスを引数としては受け取れないのだから、結局同じ問題にぶつかる。

これを解決するには、一つは抽象クラスを使う、という方法がある。


public abstract class A{
	//公開用
	public abstract void a();
	
	//パッケージ内でしか使いたくない関数
	void b(){}
}




これで、関数bはパッケージ内からしか見えない。

しかし、インターフェースではないので、このクラス以外の物をスーパークラスには出来ない。


そこで、関数の宣言をし、宣言した内容はパッケージ外からでも見れるが、パッケージ外からは実装することが許されないインターフェースというのがあったらどうだろう。
この場合、実装がパッケージ外からなされないのだから、publicの他に無修飾の関数の宣言を許可しても矛盾が起こらなくなる。


関数は見えるが実装は出来ないというのはクラスなら簡単に実現できる。



public abstract class A{
	//公開用
	public abstract void a();
	
	//パッケージ内でしか使いたくない関数
	abstract void b();
}




だが、インターフェースとなるとちょっと面倒くさい。例えば以下の様にする。

package a;
public interface A{
	<T extends A&B> void a(T t);
}

interface B{
	<T extends A&B> void b(T t);
}

Bが不可視なので、実装することができない。が、回りくどいことこの上ない。





Java8で導入予定のモジュールシステムの導入でどのようになるのか分からないが、インターフェース周りの不便もいろいろ片付けてもらえると嬉しいな。