Установить и получить методы в Java? - PullRequest
47 голосов
/ 10 июля 2011

Как я могу использовать методы set и get и зачем их использовать? Они действительно полезны? А также можете ли вы привести примеры методов set и get?

Ответы [ 15 ]

54 голосов
/ 10 июля 2011

Методы Set и Get являются шаблоном инкапсуляции данных.Вместо прямого доступа к переменным члена класса вы определяете get методы для доступа к этим переменным и set методы для их изменения.Инкапсулируя их таким образом, вы получаете контроль над общедоступным интерфейсом, если вам потребуется изменить внутреннюю работу класса в будущем.

Например, для переменной-члена:

Integer x;

У вас могут быть методы:

Integer getX(){ return x; }
void setX(Integer x){ this.x = x; }

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

22 голосов
/ 10 июля 2011

Я хочу добавить к другим ответам, что сеттеры могут использоваться для предотвращения перевода объекта в недопустимое состояние.

Например, давайте предположим, что я должен установить TaxId, смоделированный как String. Первая версия сеттера может быть следующей:

private String taxId;

public void setTaxId(String taxId) {
    this.taxId = taxId;
}

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

private String taxId;

public void setTaxId(String taxId) throws IllegalArgumentException {
    if (isTaxIdValid(taxId)) {
        throw new IllegalArgumentException("Tax Id '" + taxId + "' is invalid");
    }
    this.taxId = taxId;
}

Следующий шаг, чтобы улучшить модульность программы, - это сделать TaxId как объект, способный проверять себя.

private final TaxId taxId = new TaxId()

public void setTaxId(String taxIdString) throws IllegalArgumentException {
    taxId.set(taxIdString); //will throw exception if not valid
}

Аналогично для получателя, что если у нас еще нет значения? Может быть, мы хотим иметь другой путь, мы могли бы сказать:

public String getTaxId() throws IllegalStateException {
    return taxId.get(); //will throw exception if not set
}
8 голосов
/ 29 апреля 2014

Я думаю, вы хотите что-то вроде этого:

public class Person {

  private int age;

  //public method to get the age variable
  public int getAge(){
       return this.age
  }

  //public method to set the age variable
  public void setAge(int age){
       this.age = age;
  }
}

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

  public void setAge(int age){

       this.age = age;

       double averageCigarettesPerYear = this.smokedCigarettes * 1.0 / age;

       if(averageCigarettesPerYear >= 7300.0) {
           this.eventBus.fire(new PersonSmokesTooMuchEvent(this));
       }
  }

Конечно, это может быть опасно, если кто-то забудет позвонить setAge(int), где он должен, и устанавливает age напрямую, используя this.age.

6 голосов
/ 10 июля 2011

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

5 голосов
/ 10 июля 2011

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

private String x;

public void setX(String newX) {
    if (newX == null) {
        x = "";
    } else {
        x = newX;
    }
}

public String getX() {
    if (x == null) {
        return "";
    } else {
       return x;
    }
}
4 голосов
/ 16 октября 2014

Некоторые преимущества использования геттеров и сеттеров (известные как encapsulation или data-hiding):

(первоначально ответили здесь )

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

Пример: * * один тысяча двадцать-одна

class EncapsulationExample {
    private int readOnly = -1;  // this value can only be read, not altered
    private int writeOnly = 0;    // this value can only be changed, not viewed
    public int getReadOnly() {
        return readOnly;
    }
    public int setWriteOnly(int w) {
        writeOnly = w;
    }
}

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

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

Пример (получение значения):

class EncapsulationExample {
    private int value;
    public int getValue() {     
        return value; // return the value
    }
}

А что если я хочу вместо этого вернуть дважды значение? Я могу просто изменить свой геттер, и весь код, который использует мой пример, не нужно менять, и я получу двойное значение:

class EncapsulationExample {
    private int value;
    public int getValue() {
        return value*2; // return twice the value
    }
}

3. Делает код чище, более читабельным и понятным.

Вот пример:

Нет инкапсуляции:

class Box {
    int widthS; // width of the side
    int widthT; // width of the top
    // other stuff
}

// ...
Box b = new Box();
int w1 = b.widthS;  // Hm... what is widthS again? 
int w2 = b.widthT;  // Don't mistake the names. I should make sure I use the proper variable here!

С инкапсуляцией:

class Box {
    private int widthS; // width of the side
    private int widthT; // width of the top
    public int getSideWidth() {
        return widthS;
    }
    public int getTopWIdth() {
        return widthT;
    }
    // other stuff
}

// ...
Box b = new Box();
int w1 = b.getSideWidth(); // Ok, this one gives me the width of the side
int w2 = b.getTopWidth(); // and this one gives me the width of the top. No confusion, whew!

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

Вот good SO thread по этой теме.

Здесь good read для инкапсуляции данных.

2 голосов
/ 10 июля 2011

только потому, что правило ООП: скрытие данных и инкапсуляция. Это очень плохая практика - объявлять объект публичным и изменять его на лету в большинстве ситуаций. Также есть много других причин, но корень - Инкапсуляция в ООП. и «купи книгу или иди прочитай об объектно-ориентированном программировании», ты поймешь все об этом после прочтения любой книги по ООП.

2 голосов
/ 10 июля 2011

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

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

private String foo;

public void setFoo(String bar) {
    this.foo = bar;
}

Что произойдет, если где-нибудь в будущем вы решите, что вам больше не нужен foo, или вы хотите сделать его целым числом?Каждый объект, который использует метод setFoo, теперь необходимо изменить вместе с foo.

1 голос
/ 29 апреля 2014
public class Person{

private int age;

public int getAge(){
     return age;
}

public void setAge(int age){
     this.age = age;
}
}

Я думаю, это ты хочешь .. и это также называется pojo

1 голос
/ 10 июля 2011

Все ответы выше предполагают, что рассматриваемый объект является объектом с поведением.Продвинутая стратегия в ООП состоит в том, чтобы отделить объекты данных (которые имеют zip, имеют только поля) и объекты поведения.

С объектами данных вполне можно опустить геттеры и вместо этого иметь открытые поля.У них обычно нет сеттеров, так как они чаще всего являются неизменяемыми - их поля устанавливаются через конструкторы, и никогда больше.Взгляните на Чистый код Боба Мартина или Growing OO Software Прайса и Фримена ... для подробностей.

...