Chapter 2
Chapter 2
Объектно-ориентированное проектирование и
платформа NetBeans
2.1.Процедурное и объектно-ориентированное
программирование. Инкапсуляция
Объектно-ориентированное программирование (ООП) - это методология
программирования, опирающаяся на три базовых принципа:
- инкапсуляцию,
- наследование,
- полиморфизм.
Язык Java является объектно-ориентированным и в полном объёме использует эти
принципы. В данном параграфе рассматривается принцип инкапсуляции, наследованию и
полиморфизму посвящены отдельные параграфы.
Построение программ, основанных на ООП, принципиально отличается от более
ранней методики процедурного программирования, в которой основой построения
программы служили подпрограммы.
Программа – это набор инструкций процессору и данных, объединённых в единую
функционально законченную последовательность, позволяющую выполнять какую-нибудь
конкретную деятельность.
Подпрограмма – это набор инструкций и данных, объединённых в относительно
самостоятельную последовательность, позволяющую выполнять какую-нибудь конкретную
деятельность внутри программы. При этом подпрограмма не может работать самостоятельно
- она запускается из программы, и может получать из неё данные или передавать их в
программу.
Подпрограммы принято делить на подпрограммы-процедуры и подпрограммы-
функции. Подпрограммы-процедуры вызываются для выполнения каких-либо действий,
например – распечатки текста на принтере. Подпрограммы-функции выполняют какие-либо
действия и возвращают некоторое значение. Например, проводится последовательность
действий по вычислению синуса, и возвращается вычисленное значение. Или создаётся
сложно устроенный объект и возвращается ссылка на него (адрес ячейки, в которой он
находится).
Программы, написанные в соответствии с принципами процедурного
программирования, состоят из набора подпрограмм, причём для решения конкретной задачи
программист явно указывает на каждом шагу, что делать и как делать. Эти программы
практически полностью (процентов на девяносто) состоят из решения конкретных задач.
Программы, написанные в соответствии с принципами ООП, пишутся совершенно
иначе. В них основное время занимает продумывание и описание того, как устроены классы.
Код с описанием классов предназначен для многократного использования без внесения
каких-либо изменений. И только небольшая часть времени посвящается решению
конкретной задачи – написания такого кода с использованием классов, который в других
задачах такого типа не применить. Именно благодаря такому подходу объектное
программирование приобрело огромную популярность – при необходимости решения
сходных задач можно использовать уже готовый код, модифицировав только ту часть
программы, которая относится к решению конкретной задачи.
Подробный разбор принципов ООП будет дан позже. Пока же в общих чертах
разъясним их суть.
Самым простым из указанных в начале параграфа принципов является инкапсуляция.
Это слово в общем случае означает “заключение внутрь капсулы”. То есть ограничение
Объект
Адрес
Переменная
circle1 типа Circle
Адрес==0 null
После оператора
Поля объекта доступны через ссылку как по чтению, так и по записи. До тех пор, пока
ссылочная переменная circle1 содержит адрес Объекта1, имя circle1 является псевдонимом,
заменяющим имя этого объекта. Его можно использовать так же, как имя обычной переменной
в любых выражениях и операторах, не связанных с изменением адреса в переменной circle1.
Поскольку между ссылочными переменными одного типа разрешены присваивания,
переменная по ходу программы может сменить объект, на который она ссылается. Если
circle2 также имеет тип Circle, то допустимы присваивания вида
circle2= circle1;
Такие присваивания изменяют адреса в ячейках ссылочных переменных, но не меняют
содержания объектов.
Рассмотрим следующий участок кода:
Circle circle1=new Circle(x1,y1,r1) ;
Circle circle2=new Circle(x2,y2,r2) ;
Circle circle3;
Ему соответствует следующий рисунок:
circle3
Адрес==0
null
Проведём присваивание
circle3=circle2;
В результате получится такая картинка:
circle3
Адрес2
Обе переменные, как circle2, так и circle3, теперь ссылаются на один и тот же объект – в них
находится один и тот же Адрес2. То есть оба имени – синоним имени Объекта2. Напомним,
что сам объект, как все динамически создаваемые величины, безымянный. Таким образом,
circle2.x даст значение x2, точно так же, как и circle3.x. Более того, если мы изменим значение
circle2.x, это приведёт к изменению circle3.x – ведь это одно и то же поле x нашего Объекта2.
Рассмотрим теперь, что произойдёт при присваивании
circle1=circle2;
Этот случай отличается от предыдущего только тем, что переменная circle1 до присваивания
уже была связана с объектом.
circle3
Адрес2
Внутри фигурных скобок должно содержатся описание класса. Оно заменено многоточием.
В качестве разделителя имён пакетов в программе используется точка независимо от
типа операционной системы. Хотя в разных операционных системах вложенность папок
будет обозначаться по-разному:
в MS Windows®: pkg1\pkg2\pkg3\
в Unix и Linux: pkg1/pkg2/pkg3/
в Mac OS: pkg1:pkg2:pkg3:
После чего можно нажимать кнопку Finish – значения по умолчанию для начала
менять не стоит. Это можно будет делать потом, когда вы освоитесь со средой разработки.
/*
* Main.java
*
* Created on 21 Июнь 2006 г., 13:08
*
* To change this template, choose Tools | Template Manager
* and open the template in the editor.
*/
package javaapplication1;
/**
*
* @author User
*/
public class Main {
public Main() {
}
Его имя совпадает с именем класса. Он занимается созданием объектов типа Main. Обычно
такой конструктор вызывается из метода main, и с его помощью создаётся всего один объект,
“олицетворяющий” собой приложение. Но, вообще говоря, таких объектов в простых
программах может и не создаваться, как это и происходит в нашем случае.
Все классы и объекты приложения вызываются и управляются из метода main,
который объявлен далее и выглядит следующим образом:
System.out.println("Привет!");
Класс System, “система”, имеет поле out, “наружу”. Это объект, предназначенный
для поддержки вывода. У него есть метод println, предназначенный для вывода текста в
режиме консоли.
Консольный ввод-вывод ранее широко применялся в операционных системах,
ориентированных на работу в режиме командной строки. При этом основным средством
взаимодействия пользователей с программами служила текстовая консоль ( “пульт
управления”). В ней устройством ввода служила клавиатура, а устройством вывода – окно
операционной системы, обеспечивающее вывод текста в режиме пишущей машинки
(системным шрифтом с буквами, имеющими одинаковую ширину). Очень много примеров
программ в учебных курсах по Java ориентированы на работу в таком режиме. В настоящее
время в связи с тем, что подавляющее большинство пользователей работают с программами
в графическом режиме, работу в консольном режиме нельзя рассматривать как основную
форму ввода-вывода. Тем более, что NetBeans позволяет без особых усилий создавать
графический пользовательский интерфейс (GUI – Graphics User Interface) приложения. А
консольный режим следует применять только как промежуточный, удобный в отладочном
режиме как средство вывода вспомогательной информации.
Приведём перевод файла README.TXT, находящегося в папке dist - там же, где архив JAR,
предназначенный для распространения как файл приложения:
========================
ОПИСАНИЕ ВЫВОДА КОМПИЛЯЦИИ
========================
Когда Вы компилируете проект приложения Java, которое имеет главный класс, среда разработки (IDE)
автоматически копирует все файлы JAR-архивов, указанные в classpath ваших проектов,
в папку dist/lib. Среда разработки также автоматически прибавляет путь к каждому из этих архивов в
файл манифеста приложения (MANIFEST.MF).
Чтобы распространять этот проект, заархивируйте папку dist (включая папку lib), и распространяйте ZIP-
архив.
Замечания:
* Если два JAR-архива, указанные в classpath ваших проектов, имеют одинаковое имя, в папку lib будет
скопирован только первый из них.
* Если в classpath указана папка с классами или ресурсами, ни один из
элементов classpath не будет скопирован в папку dist.
* Если в библиотеке, указанной в classpath, также имеется элемент classpath, указанные в нём
элементы должны быть указаны в пути classpath времени выполнения проектов.
* Для того чтобы установить главный класс в стандартном проекте Java, щёлкните правой кнопкой
мыши в окне Projects и выберите Properties. Затем выберите Run и введите данные
package java_gui_example;
/**
*
* @author Вадим Монахов
*/
/**
* @param args the command line arguments
*/
public static void main(String[] args) {
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
new GUI_application().setVisible(true);
}
});
}
}
Поясним некоторые его части. Указание пакета java_gui_example, в котором будет
располагаться код класса приложения, нам уже знакомо. Декларация самого класса
GUI_application в данном случае несколько сложнее, чем раньше:
public class GUI_application extends javax.swing.JFrame
Она означает, что задаётся общедоступный класс GUI_application, который является
наследником класса JFrame, заданного в пакете swing, вложенном в пакет javax. Слово
extends переводится как “расширяет” (класс-наследник всегда расширяет возможности
класса-прародителя).
Общедоступный конструктор GUI_application()создаёт объект приложения и
инициализирует все его компоненты, методом initComponents(), автоматически
генерируемом средой разработки и скрываемом в исходном коде узлом +Generated Code.
Развернув узел, можно увидеть реализацию этого метода, но изменить код нельзя. Мы не
будем останавливаться на том, что в нём делается.
Далее следует закрытый (private) метод
Аналогичный результат можно получить и более быстрым способом – после того, как мы
выделим кнопку в окне редактирования формы (Design), в окне Navigator показывается и
выделяется имя этой кнопки. Двойной щелчок по этому имени в окне навигатора приводит
к созданию заготовки обработчика события.
Рядом с обработчиком jButton1ActionPerformed будет расположен уже имеющийся
обработчик события, срабатывающий при нажатии на пункт меню “Выход”:
Кроме того, наше приложение появляется в левом верхнем углу экрана, а хотелось бы,
чтобы оно появлялось в центре.
Для того, чтобы показать приложение в платформо-ориентированном виде (то есть в
том виде, который использует компоненты и настройки операционной системы), требуется
изменить код конструктора приложения, вставив перед вызовом метода initComponents
задание типа пользовательского интерфейса (User’s Interface, сокращённо UI):
import javax.swing.*;
import java.awt.*;
...
public GUI_application() {
try{
UIManager.setLookAndFeel( UIManager.getSystemLookAndFeelClassName() );
}catch(Exception e){};
initComponents();
Далее уже известным нам способом зададим обработчик нажатия на этот пункт меню
– выберем во всплывающем меню, возникающем при щелчке правой кнопкой мыши по
имени jMenuItem1 в окне Inspector, пункт Events/ Action/ ActionPerformed. А в обработчике
напишем оператор выхода из программы
System.exit(0);
Мы пока только создали всплывающее меню, которое доступно в нашей форме, но
ещё не назначили его никакому компоненту. Для того, чтобы назначить меню jPopupMenu1
кнопке JButton1, выделим её, и в редакторе свойств компонентов в пункте
componentPopupMenu нажмём мышью стрелку вниз, разворачивающую выпадающий список.
Кроме значения <none>, назначенного по умолчанию этому свойству для каждого
компонента, там имеется имя jPopupMenu1. Его мы и выберем.
Теперь всплывающее меню, состоящее из одного пункта “ Выйти из программы ”,
появится при щелчке правой кнопкой мыши по кнопке. Добавление других пунктов меню и
назначение им обработчиков событий проводится абсолютно так же, как для jMenuItem1.
/**
* Monthes - задаёт перечисление из 12 месяцев года: <br>
* jan,feb,mar,apr,may,jun,jul,aug,sep,oct,nov,dec <br>
* (январь, февраль и т.д.)
*/
public enum Monthes {jan,feb,mar,apr,may,jun,jul,aug,sep,oct,nov,dec};
Spring spr1= Spring.apr, spr2;
/**
*Переменная, иллюстрирующая работу с перечислениями
*/
public Monthes m1,m2=Monthes.mar,m3;
Обратите внимание, что в краткой сводке (summary) приводятся только начальные строки
соответствующей информации по элементам пакета или класса. Полную информацию можно
прочитать после перехода по гиперссылке в описании соответствующего элемента. Поэтому
важно, чтобы первые 2-3 строки информации содержали самые важные сведения.
Left – привязка к левому краю формы, Right – к правому, Top- к верхнему, Bottom – к
нижнему. По умолчанию менеджер сам выбирает варианты привязки, показывая их
пунктирными линиями.
Типичные ошибки:
Очень часто встречающаяся ошибка: путают классы, объекты и объектные
переменные. Но это совершенно разные сущности. Класс – это тип, то есть описание
того, как устроена ячейка памяти, в которой будут располагаться поля данных
объекта, и какие методы можно вызывать. Объект – это содержимое ячейки памяти
Задания
Создать новый проект NetBeans как Java Application. Импортировать классы пакета
swing. В методе main вызвать диалоговую панель JOptionPane с каким-либо
сообщением. Например, “Привет всем!”.
На основе проекта с имеющимся кодом – заготовки приложения с графическим
интерфейсом, создать приложение с кнопкой “OK”, закрывающей приложение, и
кнопкой “Нажми меня!”, вызывающей при нажатии диалоговую панель с сообщением
“Меня нажали”.
Переименовать пункты меню приложения , переведя их на русский язык.
Добавить в класс приложения общедоступное числовое поле x, инициализированное
неким значением, и поле y того же типа, но без инициализации. Добавить кнопку,
вызывающую диалоговую панель с сообщением о значениях полей x и y.
Создать документационные комментарии для поля x и методов – обработчиков
событий нажатия на кнопки. Вызвать генерацию документации для проекта,
просмотреть в ней созданные комментарии.