Соглашения Java: использовать методы получения / установки В пределах класса? - PullRequest
51 голосов
/ 11 декабря 2011

Мой профессор действительно подчеркивает необходимость защиты от утечки конфиденциальности, всегда используя методы доступа и мутаторы для доступа к частным переменным экземпляра; однако, должен ли я использовать методы получения / установки класса внутри класса?

Так, например, если у меня есть следующий класс:

public class Person 
{
    private String name;
    private int age;
}

и я хочу написать для него метод toString (). Могу я просто написать:

public String toString()
{
    return name + " " + age;
}

ИЛИ мне нужно сделать что-то вроде этого:

public String toString()
{
    return this.getName() + " " + this.getAge();
}

Ответы [ 12 ]

36 голосов
/ 11 декабря 2011

Вы МОЖЕТЕ сделать любой.Тем не менее, ваш профессор может по достоинству оценить использование методов вместо прямого доступа.Вот почему.

Допустим, у вас есть такой класс:

class SomeClass {
    private int someValue;
    private String someString;

    public SomeClass(int someValue, String someString) {
        this.someValue = someValue;
        this.someString = someString;
    }

    public int someValue() {
        return someValue;
    }

    public int someString() {
        return someString;
    }

    public String toString() {
        return someValue + ": " + someString;
    }

}

Это довольно просто, верно?Что ж, если вдруг мы захотим ИЗМЕНИТЬ реализацию того, как мы вычисляем someValue, и основать ее на someString:

public int someValue() {
    int value = 0;
    for(int i = 0; i < someString.length; i++) {
         if(someString.charAt(i) == ' ') value++;
    }
    return value;
}

Теперь вам также нужно изменить каждое место, где переменнаяsomeValue был использован.

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

И да, вы захотите использовать вызов метода вполучить someString вместо прямого доступа в последнем методе: -)

17 голосов
/ 11 декабря 2011

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

Если вы хотите скрыть часть класса от другой части того же класса, рассмотрите возможность разрыва части, которую вы хотите скрыть, в свой класс.

13 голосов
/ 11 декабря 2011

Обычно это не очень хорошая идея по ряду причин:

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

... но, как всегда, естьисключения.У некоторых сеттеров могут быть побочные эффекты (например, установка второго значения), которые вы ХОТИТЕ выполнить, тогда лучше использовать сеттер.Кроме того, если вы разрабатываете свой класс для наследования, может быть лучше пройти через метод доступа, если вы хотите, чтобы подкласс мог изменять поведение.

7 голосов
/ 11 декабря 2011

В общем, нет. Если ваш метод получения возвращает что-то отличное от значения поля, вам следует использовать метод, но в этом редком случае ваш метод должен иметь более описательное имя. Для плохого примера, если у вас есть:

public void setName(String name)
{
  _name = name;
}

и ваш получатель вернул что-то еще, например

public String getName()
{
  return _name.toUpperCase();
}

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

public String getNameAsUppercase()
{
  return _name.toUpperCase();
}
5 голосов
/ 11 декабря 2011

Нет, нет. Вы можете получить доступ к любым переменным, частным, общедоступным или защищенным, из класса.

Вот несколько таблиц, чтобы помочь вам:

enter image description here

Источник: Java Tutorials

5 голосов
/ 11 декабря 2011

Вы можете использовать аксессоры и мутаторы, но следовать этому грязному стандарту.

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

По сути, просто обращайтесь к переменным прямо из вашего класса и косвенно из любого другого места.

3 голосов
/ 11 декабря 2011

Если ваш класс (или рассматриваемые методы доступа) не final, то вам определенно следует использовать методы доступа.

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

3 голосов
/ 11 декабря 2011

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

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

Например, давайте предположим, что вы начинаете с переменной возраста в годах. Затем вы решаете позже сохранить его в секундах по какой-то причине. Но вы все равно хотите всегда печатать его годами. Таким образом, в вашем примере вы можете выполнить математику в функции toString () (и в любом другом месте, где в качестве единиц используются года), или вы можете просто изменить математику в подпрограмме getAge (), чтобы возвращать годы из секунд, и ничто другое изменить.

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

1 голос
/ 29 сентября 2016

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

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

Так что использование свойства напрямую возможно, но я рекомендую использовать get и set, потому что оно дает больше гибкости и может делать что-то большее, чем типичное назначение или получение.

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

 setName(name){

     this.name=name;
 }

То есть в коде setName("John"); равно name="John". Но представьте, что через некоторое время мы хотим установить другое свойство, когда установлено name:

 setName(name){

     this.name=name;
     this.nameIsSet=true;
 }

другой пример (образец слушателя) :

setName(name){

     this.name=name;
     this.listener.nameChanged(this.name); //we call listener that variable changed
 }

Тогда программисту нужно найти каждое задание, подобное name="John" в классе, и изменить его на новое поведение. Если используется только setName, изменение кода не требуется.

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

1 голос
/ 11 декабря 2011

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...