В чем смысл геттеров и сеттеров? [дубликат]




Возможные Дубликаты:
зачем использовать геттеры и сеттеры?






Я читал книги на Java, сказав, что это хорошо, чтобы создать сеттеры и геттеры для переменных, таких как x и y. Например:



public int getX(){
return x;
}

public void setX(int x){
this.x = x;
}


но в чем отличие от этого и



...(shape.x)...   // basically getX()


и



shape.x = 90;    // basically setX()


если сеттеры и геттеры лучше, не могли бы вы объяснить мне, какие практические проблемы возникнуть?

465   13  

13 ответов:

нескольким причинам:

  • Если вы разрешите доступ к полю типа

    формы.x = 90

тогда вы не можете добавить какую-либо логику в будущем для проверки данных.

скажем, если x не может быть меньше 100, вы не можете этого сделать, однако, если у вас были сеттеры, такие как

public void setShapeValue(int shapeValue){
  if(shapeValue < 100){
    //do something here like throw exception.
  }
}
  • вы не можете добавить что-то вроде копирования на логику записи (см. CopyOnWriteArrayList)
  • еще одна причина для доступ к полям вне вашего класса вам придется пометить их общедоступными, защищенными или по умолчанию, и таким образом Вы потеряете контроль. Когда данные очень сильно внутренние для класса breaking инкапсуляция и в целом упс методология.

хотя для констант типа

public final String SOMETHING = "SOMETHING";

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

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

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

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

использование функций getter и setter позволяет использовать ограничения и инкапсуляцию. Допустим, x-это радиус. форма.x = -10 не имеет большого смысла. Кроме того, если кто-то пытается установить недопустимое значение, вы можете напечатать ошибку, установить значение по умолчанию или ничего не делать.

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

функции Мутатора
инкапсуляция

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

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

комплексное число может быть записано на форме a + bi с реальными и мнимыми частями, хорошо поддается [gs]etRealPart и [gs]etImaginaryPart.

однако в некоторых случаях легче рассуждать о комплексных числах на полярной форме re^(iθ), предоставив [gs]etRadius (r) и [gs]etAngle (θ).

вы также можете выставить методы, такие как [gs]etComplexNumber(realPart, imaginaryPart) и [gs]etComplexNumber(radius, angle). В зависимости от типов аргументов они могут нуждаться или не нуждаться в разных именах, но тогда потребитель класса может использовать либо то, что соответствует его потребностям.

эти две формы взаимозаменяемы; вы можете довольно легко конвертировать из одной в другую, поэтому форма, которую класс использует для внутреннего хранения, не имеет отношения к потребителям этого класса. Однако потребители могут использовать любую форму. Если вы выберете форму a+bi для внутреннего представления, и выставьте это с помощью полей, а не геттеров и сеттеров, вы не только заставляете потребителей класса использовать эту форму, вы также не можете легко изменить свое мнение и заменить внутреннее представление re^(iθ), потому что это оказывается проще реализовать в вашем конкретном сценарии. Вы застряли с открытым API, который вы определили, что конкретно требует реальные и мнимые части отображаются с использованием конкретных имен полей.

еще одна веская причина для пользователей геттер и сеттер можно понять на следующем примере

public class TestGetterSetter{
    private String name ;


    public void setName(String name){
        this.name = name ;
    }


    public String getName(String name){
        return this.name ;
    }
}

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

представьте, что вы используете имя вместо его геттера. Затем, если вы хотите добавить что-то вроде значения по умолчанию (скажем, имя по умолчанию является "гостем", если он не был установлен ранее), то вам придется изменить как геттер, так и функцию sayName.

public class TestGetterSetter{
    private String name ;


    public void setName(String name){
        this.name = name ;
    }


    public String getName(String name){
        if (this.name == null ){
            setName("Guest");
        }
        return this.name ;
    }
}

нет никаких требований для геттеров и сеттеров, чтобы начать с get и set - они просто обычные функции-члены. Однако это соглашение, чтобы сделать это. (особенно если вы используете Java Beans)

одна из лучших причин, по которой я могу думать о геттерах и сеттерах, - это постоянство API класса. В таких языках, как python, вы можете получить доступ к членам по их имени и переключить их на методы позже. Потому что функции ведут себя иначе, чем члены в java, как только вы получаете доступ к свойству, вот и все. Ограничение его области позже ломает клиента.

путем обеспечивать геттеры и сеттеры программник имеет гибкость доработать члены и поведение свободно покуда придерживаться к контракт описан публичным API.

предположим, гипотетически, вы найдете библиотеку, которая лучше справляется с тем, что вы делали в своем собственном классе (YourClass). Естественная вещь, которую нужно сделать на этом этапе, - это сделать yourclass интерфейсом оболочки для этой библиотеки. Он по-прежнему имеет понятие "X", которое ваш клиентский код должен получить или установить. Естественно, на этом этапе вам в значительной степени придется писать функции доступа.

Если вы забыли использовать функции доступа и позволить вашему клиентскому коду получить доступ к вашему классу.икс непосредственно, теперь вам придется переписать весь ваш клиентский код, который когда-либо касался вашего класса.x. но если вы использовали свой класс.getX () и YourClass.setX () с самого начала вам нужно будет только переписать свой класс.

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

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

первоначально шаблон getter / setter был создан для продвижения хорошего объектно-ориентированного дизайна encapsulating внутреннее устройство class внешних interface.

  • скрытие внутреннего представления свойства

Это лучший ответ на ваш вопрос зачем использовать геттеры и сеттеры?

есть много причин. Вот лишь некоторые из них.

  1. методы доступа, в частности геттеры, часто появляются в интерфейсах. Вы не можете указать переменную-член в интерфейсе.
  2. как только вы предоставляете эту переменную-член, Вы не можете изменить свое мнение о том, как она реализована. Например, если вы видите необходимость позже переключиться на такой шаблон, как агрегация, где вы хотите, чтобы свойство "x" фактически исходило из некоторого вложенного объекта, вам придется скопировать это значение и попытаться сохранить его в синхронизации. Не хороший.
  3. большую часть времени вы гораздо лучше не разоблачение сеттер. Вы не можете сделать это с общедоступными полями, такими как x.

прежде чем попасть в ответ, мы должны знать что-то заранее...! " JavaBeans".
JavaBeans-это классы java, которые имеют свойства. Для нашей цели подумайте о свойствах как о частных переменных экземпляра. поскольку они частные, единственный способ получить к ним доступ из-за пределов своего класса через "методы" в классе.
Методы, изменяющие значение свойства, называются методы сеттера, и методы, которые извлекают a значение свойства называется методы геттер.

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

это делается путем применения инкапсуляция принцип ООП.

языковой механизм ограничения доступа к некоторым компонентам объекта.

Это означает, что вы должны определить видимость атрибутов и методов классов. Есть 3 общих тенденций:

  • Private: только класс может видеть и использовать атрибуты / методы.
  • защищено: только класс и его дочерние элементы можно видеть и использовать атрибуты / методы.
  • Public: каждый класс может видеть и использовать атрибуты / методы.

при объявлении частных / защищенных атрибутов рекомендуется создать методы для получения значения (get) и изменения значения (set). Одним из примеров видимости является [ArrayList][2] класс: он имеет size свойства знать фактический размер внутреннего массива. Только класс должны изменить его значение, так что код что-то как

public class ArrayList<E> {
    private int size;
    private Object[] array;
    public getSize() {
        return this.size;
    }
    public void add(E element) {
        //logic to add the element in the array...
        this.size++;
    }
}

в этом примере вы можете видеть, что значение размера может изменяться только внутри методов класса, и вы можете получить фактический размер, вызвав его в своем коде (не изменяя его):

public void someMethod() {
    List<String> ls = new ArrayList<String>();
    //adding values
    ls.add("Hello");
    ls.add("World");
    for(int i = 0; i < ls.size(); i++) {
        System.out.println(ls.get(i));
    }
}

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

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

потому что мы используем объектно-ориентированный язык программирования. Здесь мы используем скрытие и инкапсуляцию данных. Переменная не должна быть напрямую доступна из внешнего мира (для получения скрытия данных), поэтому мы создадим ее private so

формы.x

Это не правильно. Метод Getter и setter используется для получения и установки значения x, которое является способом достижения инкапсуляции.

Comments

    Ничего не найдено.