2017-08-20 3 views
1

私は、異なる引数型を取る同じ名前の2つの(オーバーロードされた)メソッドを持つインターフェイスを持つAPIを持っています。これらの異なるタイプは両方とも技術的に機能的なインターフェースですが、ユーザーはそのうちの1つのインスタンスを作成することを許可すべきではありません。ここでは簡単な例です:ラムダ式のターゲットとしての機能インターフェイスの停止方法を教えてください。

public class Example 
{ 
    @FunctionalInterface 
    public interface Computation 
    { 
     int compute(); 
    } 

    public interface WrappedComputation 
    { 
     Computation unwrap(); 
    } 

    public static class Solver 
    { 
     public static int solve(Computation a) 
     { 
      return a.compute(); 
     } 

     public static int solve(WrappedComputation b) 
     { 
      return solve(b.unwrap()); 
     } 
    } 

    public static void main(String... args) 
    { 
     // 'Computation' interface should be a lambda target 
     // so coder can make their own 'A' computation 
     Solver.solve(() -> { return 5 + 5; }); 

     // 'WrappedComputation' interface SHOULD NOT be a lambda target 
     // or else coder can cause runtime exceptions etc., like passing a null 'Computation' reference that will be computed 
     Solver.solve(() -> { Computation a = null; return a; }); 
    } 
} 

私が持っている唯一のアイデアはこれまでのところ、私はラムダターゲットになりたい、とのすべてでそれを実装していないインターフェイスにダミー/未使用のメソッドを追加することですクラスを実装する。それはちょっとやっかい/不要なようですが...他の提案はありますか?

答えて

2

コーダーは常にランタイム例外を引き起こす可能性があるため、これは悪い言い訳です。

あいまいさを避けたい場合は、メソッドをオーバーロードしないでください。
名前を変更します。 solveWrapped

3

インターフェイスがthe criteriaを満たす場合、APIクライアントによるラムダ式の使用を防止する方法はありません。

がラムダで問題を引き起こすのは間違っています。ラムダでできないことは、匿名の内部クラスまたは名前付きクラスでも問題ありません。次のように考えてください:

Solver.solve(new WrappedComputation(){ 
    public Computation unwrap(){ 
     Computation a = null; return a; 
    } 
}); 

これは、ラムダと全く同じセマンティクスと最終結果(ランタイム例外)を持ちます。

代わりに、代わりに欲しいのは、のいずれか制御されていない作成WrappedComputationですか?その場合には、それをそのコンストラクタエラーケースをチェックfinal classにすることを検討:

public final class WrappedComputation{ 
    private final Computation _wrapped; 
    public WrappedComputation(@NonNull wrapped){ 
     _wrapped = Objects.requireNonNull(wrapped); 
    } 
} 
関連する問題