
- •Конструкторы классов
- •Наследование
- •Модификаторы видимости
- •Перегрузка
- •Полиморфизм
- •Приемы программирования: наследование и полиморфизм
- •Конструктор по умолчанию
- •Вызов конструктора суперкласса
- •Приведение типов
- •Оператор instanceof
- •Анонимные и вложенные классы
- •Модификатор static
- •Модификатор final
- •Абстрактные классы
- •Множественное наследование
- •Описание интерфейса
- •Реализация интерфейса
- •Переменные интерфейсного типа
- •Приемы программирования: пример применения интерфейсов
- •Пакеты и области видимости Пакеты
- •Импортирование пакетов
- •Файловая структура Java-проекта
- •Области видимости классов
- •Области видимости членов класса
- •Области видимости переменных
- •Конфликты имен
- •Ход работы:
- •Задание №1
- •Задание №2
- •Задание №2
- •Задание № 3
- •Контрольные вопросы:
Модификаторы видимости
Доступ к любому члену класса – полю или методу – может быть ограничен. Для этого перед его объявлением ставится ключевое слово private. Оно означает, что к этому члену класса нельзя будет обратиться из методов других классов.
Ключевое слово public может употребляться в тех же случаях, но имеет противоположный смысл. Оно означает, что данный член класса является доступным. Если это поле, его можно использовать в выражениях или изменять при помощи присваивания, а если метод, его можно вызывать.
Ключевое слово protected означает, что доступ к полю или методу имеет сам класс и все его потомки.
Если при объявлении члена класса не указан ни один из перечисленных модификаторов, используется модификатор по умолчанию (default). Он означает, что доступ к члену класса имеют все классы, объявленные в том же пакете.
Перепишем класс Dog следующим образом:
class Dog {
private int age;// возраст
private String name; // кличка
public Dog(String n, int a) {
name = n; age = a;
}
public void voice() {
for(int i = 1; i <= age; i++) {
System.out.println("гав-гав");
}
}
}
Поля age и name окажутся скрытыми. Это значит, что мы не можем изменять их (или считывать их значение) где-либо за пределами класса. Мы не сможем в методе main() создать объект класса Dog, а затем присвоить его полю age или name новое значение, как в следующем примере:
public static void main(String[] args) {
Dog dog1 = new Dog("Тузик", 4);
dog1.age = 10; // нельзя, поле age скрыто
dog1.name = "Жучка"; // переименовать собаку тоже нельзя, поле name скрыто
dog1.voice(); // это можно, метод voice() открытый
}
Возможность скрывать поля и методы класса используется для того, чтобы уберечь программиста от возможных ошибок, сделать классы понятнее и проще в использовании. При этом реализуется принцип инкапсуляции.
Инкапсуляция означает сокрытие деталей реализации класса. Класс разделяется на две части: внутреннюю и внешнюю. Внешняя часть (интерфейс) тщательно продумывается исходя из того, каким образом могут взаимодействовать с объектами данного класса другие объекты программы. Внутренняя часть закрыта от посторонних, она нужна только самому классу для обеспечения правильной работы открытых методов.
Например, в классе Dog есть целочисленное поле age (возраст). Можно оставить его открытым, тогда его при необходимости можно будет изменить простым присваиванием (очень удобно). Но при этом ничто не мешает присвоить этому полю заведомо некорректное значение (например, 666 или -5 или 3000). Это может произойти из-за ошибки в программе. Или, к примеру, пользователь вводит возраст собаки в текстовое поле, а программа присваивает его в ответ на нажатие кнопки (и пользователь может ошибиться). Это нежелательный случай. Лучше сделать поле age закрытым (private) и добавить два открытых метода: getAge() и setAge(). Первый метод будет просто возвращать значение скрытого поля:
public int getAge() {
return age;
}
Второй метод позволит задать новый возраст собаки, производя при этом проверку присваиваемого значения.
public void setAge (int newAge) {
if (newAge < 0) System.out.println("Как это понимать? Собака еще не родилась?");
else if (newAge > 30) System.out.println("Они столько не живут");
else age = newAge;
}
Теперь мы видим, что возраст можно изменить, лишь вызвав метод setAge(), который в случае неподходящего параметра выведет в консоль сообщение и не будет ничего изменять.
Профессиональные программисты, разрабатывающие программы по объектно-ориентированной методологии, скрывают все поля своих классов, создавая для каждого из них открытые методы c приставками get и set, причем в методах set проводятся все необходимые проверки.
Заметим напоследок, что в нашем примере неправильный возраст может «прорваться» через конструктор при создании нового объекта. Никто ведь не мешает написать:
Dog dog1 = new Dog("Тузик", 2000);
Для того, чтобы этого не случилось, необходимо переписать конструктор:
public Dog(String n, int a) {
name = n;
age = setAge(a);
}
Теперь проверка осуществляется в конструкторе. Попытка завести в программе собаку с явно некорректными данными не увенчается успехом. Если возраст будет меньше 0 или больше 30, присваивание не выполнится и атрибут age будет иметь значение по умолчанию (для типа int это 0).