クラスが同じ基本的な動作、メソッドなどを実装しているが、そのクラスの複数の異なるバージョンが異なる用途に存在する可能性がある状況を考えてみましょう。私の特定のケースでは、ベクトル(リストではなく幾何学的ベクトル)があり、そのベクトルは任意のN次元ユークリッド空間(1次元、2次元など)に適用できます。このクラス/タイプはどのように定義できますか?
これは、クラステンプレートがパラメーターとして実際の値を持つことができるC ++では簡単ですが、Javaにはそのような贅沢はありません。
この問題を解決するために私が考えることができる2つのアプローチは次のとおりです。
コンパイル時に可能な各ケースの実装を持つ。
public interface Vector { public double magnitude(); } public class Vector1 implements Vector { public final double x; public Vector1(double x) { this.x = x; } @Override public double magnitude() { return x; } public double getX() { return x; } } public class Vector2 implements Vector { public final double x, y; public Vector2(double x, double y) { this.x = x; this.y = y; } @Override public double magnitude() { return Math.sqrt(x * x + y * y); } public double getX() { return x; } public double getY() { return y; } }
このソリューションは明らかに非常に時間がかかり、コーディングが非常に退屈です。この例ではそれほど悪くないように見えますが、実際のコードでは、最大4次元(x、y、z、w)でそれぞれ複数の実装を持つベクトルを処理しています。各ベクトルは本当に500行しか必要としませんが、現在2,000行を超えるコードがあります。
実行時にパラメーターを指定する。
public class Vector { private final double[] components; public Vector(double[] components) { this.components = components; } public int dimensions() { return components.length; } public double magnitude() { double sum = 0; for (double component : components) { sum += component * component; } return Math.sqrt(sum); } public double getComponent(int index) { return components[index]; } }
残念ながら、このソリューションはコードのパフォーマンスを損ない、以前のソリューションよりも厄介なコードになり、コンパイル時に安全ではありません(実際に処理しているベクトルが2次元であることはコンパイル時に保証できません。例えば)。
私は現在Xtendで開発を行っているので、Xtendソリューションが利用可能であれば、それらも受け入れられます。