class Master{ // Хозяин животного
String name; // Фамилия, имя
// Другие сведения
void getFood(int food, int drink); // Кормление // Прочее...
}
Хозяин и его домашние животные постоянно соприкасаются в жизни. Их взаимодействие выражается глаголами "гулять", "кормить", "охранять", "чистить", "ласкаться", "проситься" и пр. Для описания взаимодействия объектов применяется третий принцип объектно-ориентированного программирования — обязанность или ответственность.
В нашем примере рассматривается только взаимодействие в процессе кормления, описываемое методом eat (). В этом методе животное обращается к хозяину, умоляя его применить метод getFood ( ).
В англоязычной литературе подобное обращение описывается словом message. Это понятие переведено на русский язык напрямую ни к чему не обязывающим словом "сообщение”. Лучше было бы использовать слово "послание", "поручение" или даже "распоряжение". Но термин "сообщение" устоялся и нам придется его применять. Почему же не используется словосочетание "вызов метода", ведь говорят: "Вызов процедуры"? Дело в том, что между этими понятиями есть по крайней мере три отличия.
□ Сообщение идет к конкретному объекту, знающему метод решения задачи. В примере этот объект — текущее значение переменной person. Объекты одного и того же класса отличаются друг от друга. У каждого объекта свое текущее состояние, свои значения полей класса, и это может повлиять на выполнение метода.
□ Способ выполнения поручения, содержащегося в сообщении, зависит от объекта, которому оно послано. В нашем примере этот объект — хозяин животного. Один хозяин поставит миску с Chappi, другой бросит кость, третий выгонит собаку на улицу. Это интересное свойство называется полиморфизмом (polymorphism) и будет обсуждаться далее.
□ Обращение к методу произойдет только на этапе выполнения программы, компилятор ничего не знает про метод. Это называется "поздним связыванием" в противовес "раннему связыванию", при котором процедура присоединяется к программе на этапе компоновки.
Итак, объект sharik, выполняя свой метод eat (), посылает сообщение объекту, ссылка на который содержится в переменной person, с просьбой выдать ему определенное количество еды и питья. Сообщение записано в строке person.getFood(food, drink).
Этим сообщением заключается контракт (contract) между объектами, суть которого в том, что объект sharik берет на себя ответственность (responsibility) задать правильные параметры в сообщении, а другой объект — текущее значение экземпляра person — возлагает на себя ответственность применить метод кормления getFood(), каким бы он ни был.
Для того чтобы правильно реализовать принцип ответственности, применяется четвертый принцип объектно-ориентированного программирования — модульность (modularity).
Этот принцип утверждает: каждый класс должен составлять отдельный модуль. Члены класса, к которым не планируется обращение извне, должны быть инкапсулированы.
В языке Java инкапсуляция достигается добавлением модификатора private к описанию члена класса. Например:
private int mouseCatched; private String name; private void preserve();
Эти члены классов становятся закрытыми, ими могут пользоваться только экземпляры того же самого класса, например tuzik может дать поручение sharik.preserve ().
А если в классе Master мы напишем
private void getFood(int food, int drink);
то метод getFood () не будет найден объектами других классов и несчастный sharik не сможет получить пищу.
В противоположность закрытости мы можем объявить некоторые члены класса открытыми, записав вместо слова private модификатор public, например:
public void getFood(int food, int drink);
К таким членам может обратиться любой объект любого класса.
Знатокам C++
В языке Java словами private, public и protected отмечается каждый член класса в отдельности.
Принцип модульности предписывает открывать члены класса только в случае необходимости. Вспомните надпись на железнодорожном переезде: "Нормальное положение шлагбаума — закрытое".
Если же надо обратиться к закрытому полю класса, то рекомендуется включить в класс специальные методы доступа (access methods), отдельно для чтения этого поля (get method) и отдельно для записи в это поле (set method). Имена методов доступа рекомендуется начинать со слов get и set, добавляя к этим словам имя поля. Для классов Java, используемых как компоненты большого приложения (такие классы-компоненты в технологии Java названы JavaBeans), эти рекомендации возведены в ранг закона.