Путать с концепцией инкапсуляции Java - PullRequest
4 голосов
/ 18 февраля 2011

Добрый день!

Я читаю книгу по инкапсуляции на языке Java, в которой упоминается метод получения и установки.

Я читал, что, чтобы скрыть атрибуты, я должен пометить переменные своего экземпляра как "PRIVATE" и создать "PUBLIC" метод getter and setter для доступа к данным , Поэтому я попытался создать похожий, но не традиционный код, о чем-то следующем:

public class AddressBookEntry {

    private String name;
    private String address;
    private String telNo;
    private String email;

    public void getAllInfo() {
        name = JOptionPane.showInputDialog("Enter Name: ");
        address = JOptionPane.showInputDialog("Enter Address: ");
        telNo = JOptionPane.showInputDialog("Enter Tel. No: ");
        email = JOptionPane.showInputDialog("Enter Email Address: ");
    }
}

Показывает ли мой код выше мои переменные, потому что я назначил его напрямую? Как я могу сделать это лучше? Было бы лучше, если бы вместо этого я сделал обычный метод getter and setter и присвоил значения другому классу? Что означает «скрытие данных»?

Спасибо.

Ответы [ 6 ]

7 голосов
/ 18 февраля 2011

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

public class AddressBookEntry {

    private String name;

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

    public String getName() {
       return name;
    }
}

. Вы получите доступ к свойству name из класса UI (не рекомендуется смешивать UI и бизнес-логику в одном классе):

public class MyPane extends JFrame {

  public getAllData() {
     String name = JOptionPane.showInputDialog("Enter Name: ");
     AddressBookEntry entry = new AddressBookEntry();
     entry.setName(name);
     // You can't use entry.name = name
  }

}
5 голосов
/ 18 февраля 2011

Да и нет.Суть инкапсуляции заключается в том, что она не позволяет другим классам знать, что делает ваш класс за кулисами.Если вы храните ваш name в String (как вы это сделали здесь), читаете / пишете его из файла или делаете что-то другое, смысл инкапсуляции в том, что для пользователя вашего класса это не так.важно, потому что все они видят String getName( ) и void setName (String name).

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

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

3 голосов
/ 18 февраля 2011

Идея закрытых членов класса (атрибутов, полей) состоит в том, чтобы получить доступ к ним непосредственно внутри объявленного класса (не экземпляра!).Все остальные классы должны будут использовать другие методы доступа, например методы getter и setter.Таким образом, способ , как AdressBookEntry хранит имя, адрес, telNo и значения электронной почты, совершенно скрыт внутри класса.используйте геттеры или сеттеры, хотя иногда есть веские причины делать это и внутри класса.Использование геттеров и сеттеров иногда имеет смысл, если вы ведете какую-либо регистрацию или проверку до того, как будет установлено значение.

1 голос
/ 20 февраля 2011

Я нашел ответы выше, уже отвечая на ваш вопрос.Но я вижу еще одну проблему с вашим кодом, а именно проблему безопасности и целостности данных.Вы заполняете своего ученика прямо из ввода пользователя без каких-либо проверок на нем.Например, вы, вероятно, захотите проверить, что адрес электронной почты имеет шаблон xyz@abc.com.Злонамеренный пользователь может также ввести в строку ввода очень длинную строку, что приведет к непредвиденным ошибкам.

1 голос
/ 18 февраля 2011

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

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

1 голос
/ 18 февраля 2011

Это не нарушает инкапсуляцию, так как не предоставляет внутренние данные другому классу.Возможно, вы захотите взглянуть на Model-View-Controller (MVC), чтобы помочь отделить ваш интерфейс от ваших данных.

Традиционно вы создаете один метод получения и установки для каждой переменной по мере необходимостивот так:

public String getName() {
  return name;
}

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

Не создавайте геттеры для переменных, к которым не нужно обращаться вне класса, и не создавайте сеттеры для переменных, которые не нужно устанавливать внеthe class.

Если вы следуете MVC и используете традиционные методы получения и установки, как указано выше, вы должны получить код представления в другом месте и вызвать что-то вроде

myAddressBookEntry.setName(JOptionPane.showInputDialog("Enter Name: "));
...