Доступ к свойствам объекта (Get и Set)
На данный момент у нас есть два файла java — это Computer.java с вот таким содержимым
package testobject; public class Computer { public String name; public int ram; public int hdd; public double weight; public void on(){ int time; System.out.println("Я включился. Моя модель " + name); } public void off(){ System.out.println("Я выключился"); } public void load(){ System.out.println("Я загружаюсь. Мой объём жесткого диска равен " + hdd + " ГБ"); } }
И файл MyFirstProgram.java с таким содержимым:
package myfirstprogram; import testobject.Computer; public class MyFirstProgram { public static void main(String[] args) { Computer comp = new Computer(); comp.name = "IBM"; comp.hdd = 350; comp.on(); comp.load(); comp.off(); } }
Сегодня мы рассмотрим доступ к свойствам объекта при помощи так называемых «гетеров» и «сетеров». В прошлом уроке мы создали у объекта Computer несколько характеристик: public String name; public int ram; public int hdd; public double weight; Всё это, как вы помните, свойства объекта или ещё говорят переменные класса. Обратите внимание, что наши переменные класса используют модификатор доступа public.
Однако следует помнить, что использовать модификатор доступа public в полях класса не безопасно. Любой, кто использует объект, может напрямую изменить свойство объекта. Например, такие свойства, как объём жесткого диска, количество оперативной памяти, вес — не могут быть меньше 0. Но сейчас мы можем присвоить им отрицательные значения, так как наши переменные имеют модификатор доступа public. (comp.hdd = -100;)
Если допустить несанкционированный доступ к свойствам, то впоследствии наш объект может повести себя неадекватно.
ВЫВОДЫ
— От состояния объекта (значений переменных класса) зависит правильная работа объекта. Мы должны разрешить менять переменные так, чтобы после этого объект продолжал работать правильно.
— Задача — обеспечить безопасность изменения состояния объекта (безопасность изменения переменных класса).
Поэтому для защита был придуман механизм доступа к свойствам объекта с помощью get и set
В гетерах реализуют дополнительные действия, к примеру проверка значения или преобразование значения.
get — получить значение.
set — передать значение.
В коде представляют собой обычные методы, но имя, как правило, начинается с префиксом get или set, чтобы было понятней. К примеру getName и setName.
Таким образом мы обеспечиваем безопасность на запись значения переменной и на получение значения переменной. Также следует учитывать как можно больше факторов, которые могут «поломать» объект. Теперь рассмотрим как это будет выглядеть в программном коде.
1) Вернитесь в файл Computer.java
2) Измените модификаторы доступа в полях класса с public на private (доступный только внутри своего класса)
private String name; private int ram; private int hdd; private double weight;
Теперь доступ к нашим переменным извне класса закрыт. Теперь следует организовать доступ через «гетеры» и «сетеры.» Начнём с переменной name. Для того, чтобы имелась возможность получить значение переменной name, мы создадим метод getName с модификатором доступа public.
public String getName(){ return name; }
После Public мы указали ТИП ВОЗВРАЩАЕМОГО ЗНАЧЕНИЯ (String, поскольку будем передавать название).
Правило наименование «гетеров» — сначала пишем get потом Name — getName. Данный метод не имеет параметров — скобки оставляем пустые getName() В фигурных скобках для того, чтобы возвратить значение требуется ключевое слово return, то есть возврат. А возвращать мы будем значение переменной name.
Даже если у переменной модификатор доступа private — как мы помним она всё равно доступна внутри класса, плюс во всех методах этого класса. Внутри метода getName переменная name нам доступна на прямую. Если мы зажмём клавишу ctrl и щелкнем ЛКМ (Левой Кнопкой Мыши) по name внутри метода, то Netbeans нам покажет какую именно переменную мы возвращаем.
Теперь создадим «сетер».
public void setName(String newName){ name = newName; }
Модификатор доступа у нас будет public. Тип метода будет не String, а void, поскольку метод ничего не будет возвращать. Правило наименование «сетера» у нас set и название метода (setName), в качестве параметра метода мы передаём переменную, которая совпадает с ТИПОМ ПЕРЕМЕННОЙ NAME (String newName). Теперь открываем фигурные скобки и внутри этого метода мы должны присвоить нашей переменной name новое значение. То есть мы пишем name = newName;
Получается, что в переменную класса мы записали переданный параметр newName.
«Гетер» и «сетер» для одной переменной name создан. Давайте сделаем тоже самое для переменной ram (оперативная память).
public int getRam(){ return ram; }
По аналогии пишем public, только тип метода у нас уже будет не String, а int.
public void setRam(int newRam){ ram = newRam; }
Тип метода будет void, поскольку «сетер» ничего не возвращает, а только меняет значение переменной ram.
Теперь давайте защитим наши переменные от неправильных значений. К примеру значение оперативной памяти не может быть отрицательным. Поэтому в методе setRam, перед тем, как задать значение ram — мы должны поставить проверку. Явялется ли значение newRam положительным? Для этого нам нужно создать условие (ветвление) по аналогии с дургими языками программирования. if — если, else — иначе.
public void setRam(int newRam){ if(newRam>0){ ram = newRam; } else { System.out.println("Переданное значение " +newRam+ "не может быть отрицательным!"); } }
Если переданное значение (newRam) больше ноля, тогда мы присвоим значение newRam переменной ram, иначе мы выводим на экран сообщение о том, что переданное значение не может быть отрицательным. Перед каждым выводом сообщения будет определяться значение newRam и она будет вставляться в наш текст.
По аналогии можно сделать такую же проверку для переменных hdd (объём жесткого диска) и weight (вес), чтобы при работе с объектом Computer мы могли задавать только корректное значение этих переменных.
public void setHdd(int newHdd){ if(newHdd>0){ hdd = newHdd; } else { System.out.println("Переданное значение " +newHdd+ "не может быть отрицательным!"); } } public void setWeight(int newWeight){ if(newWeight>0){ weight = newWeight; } else { System.out.println("Переданное значение " +newWeight+ "не может быть отрицательным!"); } }
Теперь вернёмся в файл MyFirstProgram.java
package myfirstprogram; import testobject.Computer; public class MyFirstProgram { public static void main(String[] args) { Computer comp = new Computer(); comp.name = "IBM"; comp.hdd = 350; comp.on(); comp.load(); comp.off(); } }
Теперь нам недоступны переменные объекта Computer напрямую, как мы это делали в прошлом уроке. У нас доступны только методы с модифкаторами public («гетеры,» «сетеры,» on(), off() и т.д.) Напрямую мы к переменным обращаться не можем. Присвоем значение переменной name при помощи «сетера.»
1) Вместо comp.name = «IBM»; напишите comp.setName(«IBM»);
2) Вместо comp.hdd = 320; напишите comp.setHdd(320);
3) Добавьте также значение для оперативной памяти — comp.setRam(2048);
package myfirstprogram; import testobject.Computer; public class MyFirstProgram { public static void main(String[] args) { Computer comp = new Computer(); comp.setName("IBM"); comp.setRam(2048); comp.setHdd(320); comp.on(); comp.load(); comp.off(); } }
Запустим нашу программу:
run:
Я включился. Моя модель IBM
Я загружаюсь. Мой объём жесткого диска равен 320 ГБ
Я выключился
СБОРКА УСПЕШНО ЗАВЕРШЕНА (общее время: 0 секунд)
Присвоение переменных прошло корректно.
Если мы присвоим отрицательное значение comp.setHdd(-320); программа перехватит его и выведет сообщение, что переданное значение не может быть отрицательным.
Переданное значение -320 не может быть отрицательным!
Я включился. Моя модель IBM
Я загружаюсь. Мой объём жесткого диска равен 0 ГБ
Я выключился
СБОРКА УСПЕШНО ЗАВЕРШЕНА (общее время: 0 секунд)
Таким образом мы предотвратили неправильное присвоение переменным нашего объекта и защитили его от небезопасного обращения на прямую к переменным (полям) класса.
Итак файл MyFirstProgram.java выглядит примерно так:
package myfirstprogram; import testobject.Computer; public class MyFirstProgram { public static void main(String[] args) { Computer comp = new Computer(); comp.setName("IBM"); comp.setRam(2048); comp.setHdd(-320); comp.on(); comp.load(); comp.off(); } }
А файл Computer.java так:
package testobject; public class Computer { private String name; private int ram; private int hdd; private double weight; public String getName(){ return name; } public void setName(String newName){ name = newName; } public int getRam(){ return ram; } public void setRam(int newRam){ if(newRam>0){ ram = newRam; } else { System.out.println("Переданное значение " +newRam+ " не может быть отрицательным!"); } } public void setHdd(int newHdd){ if(newHdd>0){ hdd = newHdd; } else { System.out.println("Переданное значение " +newHdd+ " не может быть отрицательным!"); } } public void setWeight(int newWeight){ if(newWeight>0){ weight = newWeight; } else { System.out.println("Переданное значение " +newWeight+ "не может быть отрицательным!"); } } public void on(){ int time; System.out.println("Я включился. Моя модель " + name); } public void off(){ System.out.println("Я выключился"); } public void load(){ System.out.println("Я загружаюсь. Мой объём жесткого диска равен " + hdd + " ГБ"); } }