Рассмотрим ситуацию, когда класс реализует одно и то же базовое поведение, методы и так далее, но для разных целей может существовать несколько разных версий этого класса. В моем конкретном случае у меня есть вектор (геометрический вектор, а не список), и этот вектор может применяться к любому N-мерному евклидову пространству (1-мерное, 2-мерное, ...). Как можно определить этот класс / тип?
Это было бы легко в C ++, где шаблоны классов могут иметь фактические значения в качестве параметров, но у нас нет такой роскоши в Java.
Я могу придумать два подхода для решения этой проблемы:
Наличие реализации каждого возможного случая во время компиляции.
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; } }
Это решение, очевидно, очень трудоемкое и чрезвычайно утомительное для кода. В этом примере это не так уж плохо, но в моем собственном коде я имею дело с векторами, каждый из которых имеет несколько реализаций, с четырьмя измерениями (x, y, z и w). В настоящее время у меня более 2000 строк кода, хотя каждому вектору нужно только 500.
Задание параметров во время выполнения.
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]; } }
К сожалению, это решение снижает производительность кода, приводит к более сложному коду, чем прежнее решение, и не так безопасно во время компиляции (во время компиляции нельзя гарантировать, что вектор, с которым вы имеете дело, фактически является двумерным, например).
В настоящее время я фактически занимаюсь разработкой в Xtend, поэтому, если будут доступны какие-либо решения Xtend, они также будут приемлемы.