-非公開メソッドにハードアクセスするパターン?

public interface Target {
  String getValue();
}

public interface Processor {
  void process(Target target);
}

こういうのがあったとして、以下が実装とします。

public class TargetImpl implements Target {
  private String _value;
  public String getValue() {
    return _value;
  }
  public void setValue(String value) {
    _value = value;
  }
}

public class ProcessorImpl implements Processor {
  public void process(Target target) {
    // キャストが発生、ぬるい。
    ((TargetImpl)target).setValue("VALUE");
  }
}

TargetインターフェイスではAPIとしてgetValue()は定義していますが、setValue()は定義しておらず、API的に非公開とします。DI利用では実装クラスたるTargetImplにsetValue()を定義するケースがあるでしょう。影響範囲広いところでは書き込み可能で公開したくないけど、同じコーディングライフサイクル下で適切に管理されていれば、それでいいじゃん?と。
一方でそのTargetを取り扱いたいクラス、ProcessorImplでは、普通ならアクセスできず、具体的実装クラスにキャストしないといけない場合がでてきます。そこをDIコンテナに処理させる方法・要件もあるでしょうが、触りたいんじゃーというときに型がぬるくなるのが寂しい。ということで、以下のProcessor2インターフェイスのように、対象インターフェイスを継承した型パラメータで処理側の定義をうけとくといいかも。

public interface Processor2<T extends Target> {
  void process(T target);
}

public class Processor2Impl implements Processor2<TargetImpl> {
  public void process(TargetImpl target) {
    // キャストが無い!
    target.setValue("VALUE");
  }
}

どうかな?バイトコード的にはキャストですが。。。


コメントより。たしかにキャスト場所が代わってもらっただけかなぁ。あえて明示的なキャスト無しだと以下。

public class Main {
  public static void main(String[] args) {
    // 以下のProcessor2とTargetを取得するのは、
    // ふつうならS2がやってくれるとして。。。
    Processor2 proc = new Processor2Impl();
    Target t = new TargetImpl();
    // ここで型がぬるくなる!
    proc.process(t);
    System.out.println(t.getValue());
  }
}

万能ではないですね。