#java #методы #конструктор #полиморфизм
Например, пишу класс Vector. Вполне естественно создавать объект, принимая в конструктор
или координаты x и y, или же принимая длину вектора и угол между направлением вектора
и положительным направлением оси OX. Однако я не могу написать так:
public class Vector {
float x;
float y;
public Vector(float x, float y) {
this.x = x;
this.y = y;
}
public Vector(float length, float alpha) {
this.x = length*Math.cos(alpha);
this.y = length*Math.sin(alpha);
}
}
Компилятор, конечно, будет ругаться на неоднозначность в определении конструкторов.
Я не могу её избежать переставив аргументы местами, так как они одинаковых типов. Что
делать в таких ситуациях, когда метод/конструктор должен принимать два разных по смыслу
набора параметров, но получается так, что они имеют одинаковые типы?
Ответы
Ответ 1
В таких случаях не лишним будет использование статических фабричных методов. С использованием этого шаблона ваш код будет выглядить так: public static class Vector { public final float x; public final float y; private Vector(float x, float y) { this.x = x; this.y = y; } public static Vector coordinate(float x, float y) { return new Vector(x, y); } public static Vector radian(float length, float alpha) { return new Vector(length * Math.cos(alpha), length * Math.sin(alpha);) } } Так же, можно воспользоваться шаблоном проектирования builder. Здесь он выглядит немного громоздко, но в принципе, тоже применим: public static class Vector { ... public static VectorBuilder builder() { return new VectorBuilder(); } public static class VectorBuilder { private double length; private double alpha; private float x; private float y; public VectorBuilder setLength(float length) { this.length = length; compute(); return this; } public VectorBuilder setAlpha(float alpha) { this.alpha = alpha; compute(); return this; } private void compute() { this.x = (float) (length * Math.cos(alpha)); this.y = (float) (length * Math.sin(alpha)); } public VectorBuilder setX(float x) { this.x = x; return this; } public VectorBuilder setY(float y) { this.y = y; return this; } public Vector build() { return new Vector(x, y); } } }Ответ 2
Что-то вроде фабрики: interface SomeInterface { float setX(float x, float y); float setY(float x, float y); } class Vector { float x; float y; static SomeInterface case1 = new SomeInterface() { @Override public float setX(float x, float y) { return x; } @Override public float setY(float x, float y) { return y; } }; static SomeInterface case2 = new SomeInterface() { @Override public float setX(float x, float y) { return x * (float) Math.cos(y); } @Override public float setY(float x, float y) { return x * (float) Math.sin(y); } }; public Vector(float x, float y, SomeInterface someInterface) { this.x = someInterface.setX(x,y); this.y = someInterface.setY(x,y); } } . . . new Vector(1.0f, 2.0f, Vector.case1); new Vector(1.0f, 2.0f, Vector.case2);Ответ 3
Можете добавить костыль в виде третьего параметра и оставить один конструктор: public Vector(float a, float b, boolean isCoordinates) { if (isCoordinates) { this.x = a; this.y = b; } else { this.x = a*Math.cos(b); this.y = a*Math.sin(b); } }Ответ 4
Может так? public class Vector { float x; float y; public Vector(float[] ху) { this.x = ху[0]; this.y = ху[1]; } public Vector(float length, float alpha) { this.x = length*Math.cos(alpha); this.y = length*Math.sin(alpha); } }
Комментариев нет:
Отправить комментарий