Почему вызов метода для установки переменных лучше, чем обычная установка в конструкторе? - PullRequest
0 голосов
/ 03 сентября 2010

Я делал проект в книге по Java и наткнулся на этот пример кода.Автор книги сказал, что вместо прямой инициализации X и Y в моем конструкторе, я мог бы вместо этого вызвать метод setLocation () класса.К сожалению, у меня больше нет книги для конкретного объяснения, почему это лучше.Я не слишком разбираюсь в Java, но не проще ли ... проще присваивать значения напрямую и не беспокоиться о другом вызове функции?

//Point constructor, normal way of initializing variables

private double x;
private double y;

Point(double initial_x, double initial_y)
{
 this.x = initial_x;   
 this.y = initial_y;
} 

//Point constructor, the other way

Point(double initial_x, double initial_y)
{ 
   setLocation(initial_x, initial_y);
} 


public void setLocation(double newX, double newY)
{
   this.x = newX;
   this.y = newY; 
}

Ответы [ 7 ]

6 голосов
/ 03 сентября 2010

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

2 голосов
/ 03 сентября 2010

То же самое, что и все, что было сказано выше, с дополнительным предостережением:

Я мог бы увидеть аргумент против этой практики, если вам нужны неизменные объекты, для параллелизма или по другим причинам.Если вы делаете что-то, где несколько потоков могут воздействовать на этот объект, сеттер, вероятно, доставит вам неприятности.

1 голос
/ 03 сентября 2010

Поскольку оба экземпляра vars являются частными в любом примере, цель setLocation() в этом контексте состоит в том, чтобы позволить другим классам изменять координаты объекта Point, после его инициализации,И поскольку конструктор фактически сделал бы то же самое (опять же, только для этого простого примера), конструктор просто вызывает этот метод для простоты.

0 голосов
/ 03 сентября 2010

Этот ресурс может быть полезным:

http://en.wikipedia.org/wiki/JavaBean

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

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

Тем не менее, предоставление конструктора без аргументов не является взаимоисключающим условием предоставления удобных конструкторов с аргументами, т. Е. Вы можете иметь оба; просто убедитесь, что у вас есть простой аргумент, соответствующий описанным выше вариантам использования.

0 голосов
/ 03 сентября 2010

Если x и y являются изменяемыми и имеют нетривиальные установщики, то использование установщика для их инициализации, даже в конструкторе, может помочь избежать дублирования кода.В этом случае вы можете пометить сеттеры как final, чтобы исключить возможность переопределения производными классами этих методов и вызвать непредвиденное поведение вашего конструктора.

Если сеттеры тривиальны (простое назначение сдругого кода нет), тогда нет особых оснований использовать метод set в конструкторе.

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

0 голосов
/ 03 сентября 2010

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

private int width;
private int height;
private double diagonal;

Image(int initial_w, int initial_h)
{
 Init(initial_w, initial_h)
}

public void Init(int initial_w, initial_h)
{
 width = initial_w;
 height = initial.h
 diagonal = Math.sqrt(width*width + height*height); // constructor doesn't need to repeat this line
}
0 голосов
/ 03 сентября 2010

У вас есть больше контроля, когда они установлены.

...