この質問は少し先進的なので、やや複雑です。私は可能な限り明確になるよう努力して努力します。Java Genericsを使用してタイプ制限を適用する方法
タイトルのとおり、Java Genericsを使用して、トップレベル(メイン)のオブジェクトを構築するときにタイプ制限を適用したいと考えています。
私はJavaのジェネリックを実際に使用したことはありませんが、実装方法がわかりません。
オブジェクトを作成するときにタイプ制限を適用したいと思います。
ここでは、メソッドの初期化と呼び出しを行うNumberEngineオブジェクトを呼び出すトップレベルのmainメソッドがあります。 setExecuteBehavior()を呼び出すと、RunNumberEvaluation型のオブジェクト(RunStringEvaluationとともにExecutionBehaviorというインターフェイスを実装しています)を渡します。
名前が示すように、NumberEngineはNumberでのみ動作し、Stringでは動作しないため、setExecuteBehavior()にRunStringEvaluation型のオブジェクトを渡すのは不適切です。コンパイル時にこの動作を強制するにはどうすればよいですか?
public static void main(String[] args) {
NumberEngine numberEngine = new NumberEngine();
numberEngine.init("/path/to/forms");
numberEngine.getEngineVesion();
numberEngine.setExecuteBehavior(new RunNumberEvaluation);
numberEngine.performExecution();
// Here this should not compile, essentially throw me a compile error saying it can only accept
// an object of type RunNumberEvaluation, sincle NumberEngine can only run
// objects of type RunNumberEvaluation, etc...
numberEngine.setExecuteBehavior(new RunStringEvaluation());
numberEngine.performExecution();
}
だからここに私は基本的にNumberEngineのsetExecuteBehaviorは数字だけではなく文字列に関連するデータの処理などのそれにreleventある行動を受け入れるようにしたいと思います。また、StringEngineの場合も同様です。私はStringEngineがNumberではなくStringsにしか関係のないオブジェクトを受け入れるようにします。
これをJava genericsでどうすれば実現できますか?私は「何の実例として、以下の作業のコードが含まれている私は...このような何か...これは理にかなっている場合
NumberEngine<? extends Numbers> extends Engine
さえわからない
を考えていた
通信しようとしています。
私はStringEngine、NumberEngineなどのような多くの拡張コンクリートクラスを持つ抽象クラスであるEngine型のオブジェクトを持っています。私はアルゴリズムの機能性を、そのインタフェースを実装するクラスとのインタフェースに切り離しました。
基本抽象クラス
public abstract class Engine {
ExecuteBehavior executeBehavior;
public void setExecuteBehavior(ExecuteBehavior executeBehavior) {
this.executeBehavior = executeBehavior;
}
public void performExecution() {
executeBehavior.execute();
}
public abstract void init(String pathToResources);
}
コンクリート実装するクラス1
public class StringEngine extends Engine {
public StringEngine() {
executeBehavior = new RunNumberEvaluation();
}
@Override
public void init(String pathToResources) {
System.out.println("Initializing StringEngine with resources "+pathToResources);
System.out.println("Successfully initialized StringEngine!");
}
}
コンクリート実装するクラス2
public class NumberEngine extends Engine {
public NumberEngine() {
executeBehavior = new RunStringEvaluation();
}
@Override
public void init(String pathToResources) {
System.out.println("Initializing NumberEngine with resources "+pathToResources);
System.out.println("Successfully initialized NumberEngine!");
}
}
アルゴリズムインタフェース
public interface ExecuteBehavior {
void execute();
}
アルゴリズム実装1
public class RunNumberEvaluation implements ExecuteBehavior {
@Override
public void execute() {
// some processing
System.out.println("Running numeric evaluation");
}
}
アルゴリズム実装2
public class RunStringEvaluation implements ExecuteBehavior {
@Override
public void execute() {
// some processing
System.out.println("Running string evaluation");
}
}
あなたは気づいていないが、ここで私はを利用していた場合戦略パターン私は静的で変化しないコードから、さまざまなアルゴリズムをインターフェースを介して家族に分けます。
編集:ここで使用されている戦略パターンを維持したいと思います。
興味深い提案
StringEngine
ではなく、私が移動した場合、その後NumberEngine
そしてRunStringEngine、 'setExecuteBehavior()'をEngineからサブクラスに継承すると、私は採用しているストラテジパターンを破ることになります – barthelonafan
オブジェクトの向きが新しくなりましたか?あなたが 'setExecuteBehavior()'抽象を作成した場合、継承は維持されます。メソッドがAPIの一部であり、そうでない場合はそうしない場合は、これを行います。 – scottb
私はコードの再利用を述べたはずですが、もっと重要なことに、これは戦略パターンを破るでしょうか? – barthelonafan