Подтвердить что ты не робот

Соглашения Java: использовать getters/setters внутри класса?

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

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

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

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

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

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

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

Ответ 1

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

Скажем, у вас есть класс вроде этого:

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 вместо прямого доступа в последнем методе: -)

Ответ 2

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

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

Ответ 3

Как правило, это не очень хорошая идея по ряду причин:

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

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

Ответ 4

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

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

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

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

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

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

Ответ 5

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

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

enter image description here

Источник: Учебники Java

Ответ 6

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

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

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

Ответ 7

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

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

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

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

Ответ 8

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

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

Ответ 9

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

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

Ответ 10

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

но если вы используете установщик, вы можете просто поставить точку прерывания внутри метода setter и посмотреть, сколько раз назначается переменная.

Ответ 11

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

Должны использоваться не используемые средства. Свойство может использоваться напрямую (только внутри класса, если свойство является частным - и должно быть), но в хорошей практике это использовать 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, то изменение кода не должно выполняться.

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