Где я работаю, я вижу много классов, которые делают такие вещи:
public class ClassThatCallsItsOwnGettersAndSetters {
private String field;
public String getField() {
return field;
}
public void setField(String field) {
this.field = field;
}
public void methodWithLogic() {
setField("value");
//do stuff
String localField = getField();
//do stuff with "localField"
}
}
Если бы я написал это с нуля, я бы написал methodWithLogic()
так:
public class ClassThatUsesItsOwnFields {
private String field;
public String getField() {
return field;
}
public void setField(String field) {
this.field = field;
}
public void methodWithLogic() {
field = "value";
//do stuff
//do stuff with "field"
}
}
Я чувствую, что когда класс вызывает свои собственные методы получения и установки, это затрудняет чтение кода. Для меня это почти означает, что сложная логика происходит при вызове этого метода, хотя в нашем случае это почти никогда не происходит. Когда я отлаживаю какой-то незнакомый код, кто скажет, что ошибка не является побочным эффектом в этом методе? Другими словами, это заставляет меня совершать множество дополнительных поездок по пути понимания кода.
Есть ли преимущества у первого метода? Первый метод на самом деле лучше?
java
object-oriented
programming-practices
Даниэль Каплан
источник
источник
Ответы:
Я не буду говорить, что лучше или хуже, потому что это отчасти зависит от вашей ситуации (на мой взгляд). Но учтите, что ваши геттеры и сеттеры могут изменить реализацию позже, и обход их пропустит эту логику.
Например, что произойдет, если вы добавите «грязный» флаг к некоторым полям установщика позже? Вызывая ваши сеттеры во внутреннем коде, вы устанавливаете грязный флаг, не меняя никакого другого кода. Во многих ситуациях это было бы хорошо.
источник
setField()
с самого начала, вы только что ввели ошибку.Вызов сеттера напрямую сам по себе не является проблемой. Вопрос действительно должен быть: почему наш код везде имеет сеттеры?
Изменчивые классы - опасная игра, особенно когда сам класс управляет своим собственным состоянием. Подумайте, сколько из этих сеттеров действительно должно существовать. Сколько можно установить в конструкторе и затем полностью инкапсулировать сам класс?
Если поле должно быть настраиваемым извне, спросите себя, должен ли там быть метод с логикой. Ваш класс действительно просто класс данных / состояний? Есть ли у этого класса более одной ответственности?
Не поймите меня неправильно, будут случаи, когда это нормально. Я не говорю, что вы должны полностью исключить сеттеры на классах с помощью логики. Но это должно быть исключением, а не правилом. И в тех немногих случаях должно быть очевидно, к какому доступу получить доступ напрямую.
источник
Да, методы вашего класса должны вызывать методы получения и установки. Весь смысл в написании геттеров и сеттеров - это проверка будущего. Вы можете сделать каждое свойство полем и напрямую предоставлять данные пользователям класса. Причина, по которой вы строите геттеры и сеттеры, не обязательно состоит в том, что сейчас есть сложная логика, но чтобы интерфейс не сломался в будущем, если вам придется его добавлять.
источник
someField=newValue; refresh();
Если метод позволяет задавать несколько полей, вызов сеттеров для записи этих полей вызовет избыточные операции «обновления». Запись всех полей и последующий вызовrefresh()
может привести к более эффективной и гладкой работе.Чтобы ответить на ваши вопросы одним словом, да.
Наличие вызова класса для своих собственных методов получения и установки добавляет расширяемость и обеспечивает лучшую основу для будущего кода.
Скажем, у вас есть что-то вроде этого:
Вызов сеттеров для year и make в настоящее время может не добавить никакой функциональности, но что если вы захотите добавить что-то вроде проверки входных данных для сеттеров?
источник
Одна вещь, которая не была упомянута, состоит в том, что геттер и сеттеры (как и все методы) являются виртуальными в Java. Это добавляет еще одну возможность всегда использовать их в вашем коде. Другой пользователь может расширить ваш класс, переписав ваши методы получения и установки. Ваш базовый класс будет тогда использовать данные подкласса вместо своих собственных. В языке, где вы явно помечаете виртуальные функции, это гораздо удобнее, поскольку вы можете предсказать и объявить, с какими функциями это можно сделать. В Java это то, о чем вы всегда должны знать. Если это желаемое поведение, то использование их в вашем коде - это хорошо, иначе не так уж и много.
источник
Если вы пытаетесь выполнить что-то, предоставляемое общедоступным интерфейсом, используйте геттеры / сеттеры.
Тем не менее, как владелец / разработчик класса, вам разрешен доступ к закрытым разделам вашего кода (конечно, из класса), но вы также несете ответственность за уменьшение опасности.
Так что, возможно, у вас есть геттер, который выполняет итерацию по какому-то внутреннему списку, и вы хотите получить текущее значение без увеличения итератора. В этом случае используйте закрытую переменную.
источник
Да. Геттеры и сеттеры представляют состояние, поэтому переверните этот вопрос - хотите ли вы отслеживать несколько способов изменения состояния объектов одним и тем же способом, если нет необходимости?
Чем меньше вещей вы должны отследить, тем лучше - вот почему с неизменными объектами легче иметь дело.
Подумайте, ничто не мешает вам иметь как публичное поле, так и публичный метод получения / установки - но что бы вы получили?
В некоторых случаях может быть желательным или даже необходимым прямой доступ к полю по одной или нескольким причинам, не следует уклоняться от этого, если это произойдет. Но вы должны делать это только в том случае, если для этого есть определенная выгода.
источник
Оба метода имеют свои варианты использования. Так как общедоступный установщик сохраняет значение поля (и / или связанные значения) непротиворечивым, вы должны использовать установщик, когда логика вашего метода не мешает этой логике согласованности. Если вы просто установили свое «свойство», используйте setter. С другой стороны, существуют ситуации, когда вам нужен прямой доступ к некоторым полям, например, массовые операции с тяжелым установщиком или операции, где концепция сеттера слишком проста.
Вы несете ответственность за поддержание последовательности. Сеттер делает это по определению, но не может охватывать сложные случаи.
источник
Я бы сказал нет ..
Если ваши геттеры / сеттеры просто получают и устанавливают (без ленивой инициализации, без проверок и т. Д.), Тогда просто используйте ваши переменные. Если в будущем вы измените свои методы получения / установки, вы можете очень хорошо изменить свое
methodWithLogic()
(потому что меняется ваш класс), и вы можете вызвать получателя / установщика вместо прямого назначения. Вы можете задокументировать этот вызов для метода получения / установки (поскольку будет странно вызывать метод получения / установки, когда остальная часть кода вашего класса напрямую использует переменную).JVM будет выполнять частые звонки получателям / установщикам. Таким образом, это никогда не проблема производительности. Преимущество использования переменных - читабельность, и я думаю, я бы пошел на это.
Надеюсь это поможет..
источник