2010-05-16 4 views
10

Каковы варианты использования двух конструкторов с одной и той же подписью?Почему у вас есть два конструктора с одинаковой подписью?

Редактировать: вы не можете сделать это на Java, из-за чего эффективная Java говорит, что вам нужна статическая фабрика. Но мне было интересно, зачем вам это делать в первую очередь.

+1

erm, вы не можете, не так ли? –

+5

Во-первых, не могли бы вы показать нам пример, который компилируется? –

+0

Для записи вы имеете в виду два конструктора * в том же классе * с одной и той же сигнатурой? – harpo

ответ

15

Причины вы бы думать вы хотели бы сделать это, что вы нашли себя в ситуации, когда переменные типа не достаточно контекст.

Например, я мог бы одурачить себя мыслью, что мне нужно дать свои два класса класса Point: один, который работает по X и Y, и поровну, и радиан. Оба могут быть представлены как float.

Так что я думаю, мне нужны были два конструктора с одинаковыми сигнатурами (float, float).

Dr.Блох отмечает, что это лучше сделать фабричные методы:


    public static Point newPointByDegreesAndRadians (float degrees, float radians); 
    public static Point newPointByXandY (float x, float y); 

Кстати, еще одна альтернатива фабричных методов для создания типов, которые несут в себе контекст, который отсутствует из типов данных, как это:


    public class CoordinatesXY { 
     float X; 
     float Y; 
     ... 
    } 
    public class CoordinatesDegreesRadians { 
     float degrees; 
     float radians; 
     ... 
    } 
    public Point (CoordinatesXY coordinates) { ... } 
    public Point (CoordinatesDegreesRadians coordinates) { ... } 

Думаете ли вы, что это яснее, чем фабричные методы - это вопрос вкуса. Для этого конкретного случая мое собственное чувство состоит в том, что два класса координат полезны только в том случае, если ваш дизайн делает координаты полезными сами по себе, отдельно от точки в этих координатах.

5

Класс не может иметь двух конструкторов с одинаковой подписью.

From the JLS:

8.8.2 Подпись Конструктор

Это ошибка во время компиляции, чтобы объявить два конструктора с переопределяют-эквивалентными (§8.4.2) подписей в классе. Ошибка компиляции для объявления двух конструкторов, чья подпись имеет такое же стирание (§4.6) в классе.

+2

Я знаю, что Java этого не позволяет. Вот почему нам нужен статический завод. Но зачем нам создавать разные конструкторы на месте. – unj2

2

Вы бы этого не сделали, и вы все равно не можете. Он не будет компилировать файлы классов в байт-код, так как нет возможности разграничить их между собой, чтобы решить, какой из них использовать.

+0

На самом деле, разрешение перегрузки происходит во время компиляции, поэтому программа никогда не будет пытаться найти правильный конструктор. – Joey

+4

Разве это не то, что я сказал, или я просто неправильно вас понял? – AaronM

1

@kunjaan - для такой идеи существует очень мало случаев использования, даже если есть технически обоснованный способ сделать это (чего в Java нет - см. Другие ответы).

Одним из возможных вариантов использования может быть реализация различных конструкторов на основе какого-либо внешнего условия - например, конструктор, который может выделять определенную память, если он недоступен, или повторно использовать эту память из некоторого общего пула в программе, если он стал доступен.

Другим примером этого может быть конструктор, который будет реализовывать определенные вещи, используя более эффективный системный вызов, если текущая архитектура поддерживает этот системный вызов. Кстати, оба этих примера немного сложнее представить на Java, но их легче представить на C++ -land, но вы надеетесь получить общую идею.

В любом случае это будет фактически закодировано либо с фабрикой, как вы упомянули, либо с одним конструктором, который реализует какое-то решение на основе среды и вызывает вспомогательный метод с различными сигнатурами, чтобы фактически выполнить необходимую инициализацию это зависит от реализации, например (В псевдокоде, языке независимого)

function helper_initializer(signature for case 1) { 

} 
function helper_initializer(signature for case 2) { 

} 
function constructor() { 
    // constructor logic here 
    if (environmental_consdition() == 1) { 
     this->helper_initializer(signature for case 1); 
    } else { 
     this->helper_initializer(signature for case 2); 
    } 
} 
3

Чтобы ответить на ваш новый отредактированный вопрос, было бы намерение, если бы у вас был класс, который мог бы иметь два логически разных действия, но это одна и та же подпись.

Например, у вас есть класс Person, который заботится о чье-то имя и место рождения.

public Person(String name) { ... } 
public Person(String placeOfBirth) { ... } 

Очевидно, что это не работает.

Вы должны использовать завод:

public static Person personWithName(String name) { ... } 
public static Person personFromPlace(String placeOfBirth) { ... } 

Очевидно надуманный пример, но это общая идея ...

+0

Это отличный пример. – unj2

11

Причины вы хотите иметь две (или более) конструкторов с та же подпись заключается в том, что тип данных не является синонимом значения.

Простым примером может служить класс Line.

Вот один конструктор: public class Line(double x1, double y1, double x2, double y2)

Вот еще: public class Line(double x1, double y1, double angle, double distance)

Первый конструктор определяет две концевые точки линии. Второй конструктор определяет одну конечную точку, а угол и расстояние до второй конечной точки.

Java не может различать два конструктора класса Line, true. Но есть веские причины для того, чтобы 2 или более конструктора имели одну и ту же подпись.

+1

+1 - первое предложение - ключевой момент. –

Смежные вопросы