
Основные понятия ооп
Описание класса начинается с ключевого слова class, после которого указывается идентификатор — имя класса. Затем в фигурных скобках перечисляются атрибуты и методы класса. Атрибуты называются полями (в дальнейшем мы будем использовать это наименование). Поля и методы называются членами класса.
Поля описываются как обычные переменные.
Опишем для примера класс Dog (собака). У него будет два поля: кличка и возраст. При описании поведения собаки в этом простом примере ограничимся лаем. Конечно, лаять по-настоящему наша собака не будет (ведь это всего лишь программная конструкция), она будет выводить в консоль «гав-гав». Чтобы было интереснее, предположим, что все собаки, с которыми имеет дело наша программа, умны настолько, что когда их вынуждают лаять, они говорят «гав-гав» столько раз, сколько им лет.
class Dog {
Int age; // возраст
String name; // кличка
public void voice() {
for (int i = 1; i <= age; i++) {
System.out.println("гав-гав");
}
}
}
Самое главное — понять, что означает, когда некоторые переменные (поля) и функции (методы) собраны (описаны) в каком-то классе.
Класс должен описывать некоторое законченное понятие. Это может быть понятие из предметной области программы (собака, велосипед, аквариум, сессия) или понятие, необходимое для работы самой программы (очередь, список, строка, окно, кнопка, программа*).
Полями класса должны быть данные, относящиеся к этому понятию. Для собаки это возраст, кличка, порода и т.д., а для сессии — дата начала, продолжительность и т.д.
Методы класса, как правило, работают с данными этого класса. Например, метод voice() в нашем примере обращается к полю age (возраст).
Когда какой-то класс описан, могут создаваться объекты этого класса и с ними можно работать, вызывая их методы (кормить собаку, выгуливать, просить ее лаять — словом делать все то, что позволяет поведение класса, т.е. совокупность его методов).
Для обращения к объектам удобно использовать переменные, имеющие тип класса. Например, для работы с собаками опишем переменную типа Dog:
Dog x;
Переменная типа класса является ссылочной переменной, она не хранит данные (как переменные простых типов int, char и т.д.), а указывает на место в памяти, где эти данные хранятся (как переменные типа массива). Данными, на которые указывает только что описанная переменная x, может быть объект класса Dog. Его необходимо предварительно создать командой new:
x = new Dog();
Теперь переменная x указывает на некий объект класса Dog, хранящий в памяти свои данные (возраст и кличку). Кроме того, эту собаку можно заставить лаять, вызвав соответствующий метод командой:
x.voice();
Для того, чтобы обратиться к члену класса, необходимо указать его имя после имени объекта через точку.
Обратите внимание, «залаяла» именно та собака, на которую «указывала» переменная x. Если в программе были созданы другие собаки, они будут молчать до тех пор, пока не будет вызван их метод voice().
Таким образом, когда данные (поля) и команды (методы) описываются в одном классе, они оказываются тесно связаны друг с другом в объектах этого класса. Метод вызывается не сам по себе, а для конкретного объекта и работает с полями именно этого объекта.
Поэтому команды
voice();
age += 1;
не имеют никакого смысла, если употребляются вне методов класса Dog. Обязательно указание на конкретный объект, с которым производится действие. Внутри метода указание на конкретный объект вовсе не обязательно: в рассмотренном примере запись
for (int i = 1; i <= age; i++)
о ключевом слове this
означает, что для определения «продолжительности» лая будет проверяться возраст того самого объекта, для которого будет вызван данный метод. Этот объект обозначается ключевым словом this.
Метод voice() можно было описать и так:
public void voice() {
for (int i = 1; i <= this.age; i++) {
System.out.println("гав-гав");
}
}
Ключевое слово this в этом примере наглядно указывает, что используется атрибут age именно того объекта класса Dog, для которого вызывается метод voice().
Когда имя метода или атрибута записывается без указания объекта, всегда подразумевается объект this.
Конструкторы классов
Конструктор — это особенный метод класса, который вызывается автоматически в момент создания объектов этого класса. Имя конструктора совпадает с именем класса.
Например, в классе Dog может быть конструктор с двумя параметрами, который при создании новой собаки позволяет сразу задать ее кличку и возраст.
public Dog(String n, int a) {
name = n;
age = a;
}
Конструктор вызывается после ключевого слова new в момент создания объекта. Теперь, когда у нас есть такой конструктор, мы можем им воспользоваться:
Dog dog1 = new Dog("Тузик", 2);
В результате переменная dog1 будет указывать на «собаку» по кличке Тузик, имеющую возраст 2 года. Кстати, этот возраст можно узнать, заставив собаку лаять командой
dog1.voice();*
Конструкторы добавляются в класс, если в момент создания объекта нужно выполнить какие-то действия (начальную настройку) с его данными (полями). Сразу задать кличку и возраст собаки более естественно, чем каждый раз порождать безымянного щенка, а затем давать ему имя и быстро выращивать до нужного возраста (с учетом того, что программа скорее всего обрабатывает данные о собаках, которые на самом деле уже давно родились). Хотя до появления ООП программисты часто делали именно так.