Страницы

Поиск по вопросам

вторник, 28 января 2020 г.

Как избежать определения двух методов/конструкторов с одинаковыми параметрами?

#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); } }

Комментариев нет:

Отправить комментарий