【Java】「InterfaceのAとBを実装する型」という書き方がローカル変数で実現できない
何を言っているかという話だが、こういうこと↓
public class Main { public static void main(String[] args) throws Exception { Ccc c = new Ccc(); System.out.println(c.concatB(c.concatA("hoge"))); // hogeAB System.out.println(concatHelper(c, "hogehoge")); // hogehogeAB // このcに当たるような存在をclassじゃなくてInterface名で指定したい。。 // 欲しいのはAaaとBbbを実装しているやつだからね。Cccクラスじゃないからね(´・ω・`) } static <T extends Aaa & Bbb> String concatHelper(T t, String str) { return t.concatB(t.concatA(str)); } interface Aaa { default String concatA(String str) { return str.concat("A"); } } interface Bbb { default String concatB(String str) { return str.concat("B"); } } static class Ccc implements Aaa, Bbb { } }
設計が悪いと言われればそれまでなんだろうけど、リフレクションなんかを使用している時に、「複数のInterfaceを実装しているクラス」という型を宣言したい時がある。
もちろん、上記でいえばconcatHelper()
のような形で宣言できるのは知っているのだけど、これを普通のローカル変数の型として定義したい(何というか、スコープがメソッドなのが気に食わない…)。
※これを試しているのはjava version "1.8.0_192" です。10以降(?)で導入されたvarで解決できるかは不明。
あとこれ書いてて思い出したのは、Interfaceを無名関数で複数実装ができないのもちょっと悲しいなぁと思う。
今はできるんだろうか。 Scalaならできるんだろうなぁ…とか思って試したら両方ともできた。やっぱり柔軟な書き方ができるのは羨ましいなー;;
object ScalaMain { def main(args: Array[String]): Unit = { val sccc: Sccc = new Sccc() println(sccc.concatB(sccc.concatA("hoge"))) // hogeAB println(concatHelper(sccc, "hogehoge")) // hogehogeAB val x: Saaa with Sbbb = new Saaa with Sbbb println(x.concatB(x.concatA("foo"))) // fooAB val y: Saaa with Sbbb = sccc println(y.concatB(y.concatA("foofoo"))) // foofooAB } private def concatHelper[T <: Saaa with Sbbb](t: T, str: String): String = { t.concatB(t.concatA(str)) } trait Saaa { def concatA(str: String): String = str.concat("A") } trait Sbbb { def concatB(str: String): String = str.concat("B") } class Sccc extends Saaa with Sbbb { } }