Rozważmy sytuację, w której klasa implementuje to samo podstawowe zachowanie, metody itd., Ale istnieje wiele różnych wersji tej klasy do różnych zastosowań. W moim szczególnym przypadku mam wektor (wektor geometryczny, a nie listę) i ten wektor może mieć zastosowanie do dowolnej N-wymiarowej przestrzeni euklidesowej (1 wymiar, 2 wymiar, ...). Jak można zdefiniować tę klasę / typ?
Byłoby to łatwe w C ++, gdzie szablony klas mogą mieć rzeczywiste wartości jako parametry, ale nie mamy tego luksusu w Javie.
Dwa podejścia, które mogę wymyślić, które można zastosować w celu rozwiązania tego problemu, to:
Posiadanie implementacji każdego możliwego przypadku w czasie kompilacji.
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; } }
To rozwiązanie jest oczywiście bardzo czasochłonne i niezwykle uciążliwe dla kodu. W tym przykładzie nie wydaje się to takie złe, ale w moim rzeczywistym kodzie mam do czynienia z wektorami, które mają wiele implementacji, z maksymalnie czterema wymiarami (x, y, z i w). Obecnie mam ponad 2000 wierszy kodu, chociaż każdy wektor naprawdę potrzebuje tylko 500.
Określanie parametrów w czasie wykonywania.
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]; } }
Niestety to rozwiązanie szkodzi wydajności kodu, powoduje powstanie bałaganu w porównaniu z poprzednim rozwiązaniem i nie jest tak bezpieczne w czasie kompilacji (nie można zagwarantować w czasie kompilacji, że wektor, z którym mamy do czynienia, jest w rzeczywistości dwuwymiarowy, na przykład).
Obecnie rozwijam się w Xtend, więc jeśli jakiekolwiek rozwiązania Xtend będą dostępne, będą one również do przyjęcia.