Смекни!
smekni.com

Общие представления о языке Java 5 (стр. 43 из 68)

Приводить тип можно как в сторону генерализации, так и в сторону специализации.

Приведение в сторону генерализации является безопасным, так как объект класса-потомка всегда является экземпляром прародителя, хоть и усложнённым А вот приведение в сторону специализации является опасным – вполне допустимо, что во время выполнения программы окажется, что объект, назначенный переменной, не является экземпляром нужного класса. Например, при приведении (Circle)figure может оказаться, что переменной figure назначен объект типа Dot, который не может быть приведён к типу Circle. В этом случае возникает исключительная ситуация приведения типа (typecast).

Возможна программная проверка того, что объект является экземпляром заданного класса:

if(figure instanceof Circle)

System.out.println("figure instanceof Circle");

Иногда вместо работы с самими классами бывает удобно использовать ссылки на класс. Они получаются с помощью доступа к полю .class из любого класса.

Возможно создание переменных типа “ссылка на класс”:

Class c=Circle.class;

Их можно использовать для обращения к переменным класса и методам класса. Кроме того, переменных типа “ссылка на класс” можно использовать для создания экземпляров этого класса с помощью метода newInstance():

Circle circle=(Circle)c.newInstance();

Возможна программная проверка соответствия объекта нужному типу с помощью ссылки на класс:

if(figure.getClass()==Circle.class)

circle= (Circle)figure;

…;

Но следует учитывать, что при такой проверке идёт сравнение на точное равенство классов, а не на допустимость приведения типов. А вот оператор isInstance позволяет проверять, является ли объект figure экземпляром класса, на который ссылается c :

if(c.isInstance(figure))

System.out.println("figure isInstance of Circle");

Рефакторинг

Одним из важных элементов современного программирования является рефакторинг – изменение структуры существующего проекта без изменения его функциональности.

Приведём три наиболее часто встречающихся примера рефакторинга.

· Во-первых, это переименование элементов программы – классов, переменных, методов.

· Во-вторых, перемещение элементов программы с одного места на другое.

· В-третьих, инкапсуляция полей данных.

В сложных проектах, конечно, возникают и другие варианты рефакторинга (например, выделение части кода в отдельный метод – “Extract method”), но с упомянутыми приходится встречаться постоянно. Поэтому рассмотрим эти три случая подробнее.

Первый случай - переименование элементов программы.

Для того, чтобы в среде NetBeans переименовать элемент, следует щёлкнуть по его имени правой кнопкой мыши. Это можно сделать в исходном коде программы, а можно и в окне Projects или Navigator. В появившемся всплывающем меню следует выбрать Refactor/Rename… После чего ввести новое имя и нажать кнопку “Next>”.

Переименование класса. Шаг 1

Переименование класса. Шаг 2

Если галочка “Preview All Changes” (“Предварительный просмотр всех изменений”) не снята, в самом нижнем окне, Output (“Вывод”), появится дерево со списком мест, где будут проведены исправления. В случае необходимости галочки можно снять, и в этих местах переименование проводиться не будет. При нажатии на кнопку “Do Refactoring” (“Провести рефакторинг”) проводится операция переименования в выбранных местах программы. В отличие от обычных текстовых процессоров переименование происходит с учётом синтаксиса программы, так что элементы, не имеющие отношения к переименовываемому, но имеющие такие же имена, не затрагиваются. Что в выгодную сторону отличает NetBeans от многих других сред разработки, не говоря уж об обычных текстовых редакторах.

Переименование класса. Шаг 3

Требуется быть внимательными: довольно часто начинающие программисты не замечают появления в окне Output списка изменений и кнопки “Do Refactoring”. Особенно если высота этого окна сделана очень малой. Если в диалоге переименования (шаг 2) флажок “Preview all Changes” снят, при нажатии на кнопку “Next>” сразу происходит рефакторинг.

Следует также отметить, что после проведения рефакторинга возможен возврат к первоначальному состоянию (“откат”, операция undo). Обычно такая операция осуществляется с помощью главного меню проекта (кнопка Undo или пункт меню Edit/Undo), но в случае рефакторинга требуется правой клавишей мыши вызвать всплывающее окно и выбрать пункт Refactor/Undo. Откат может быть на несколько шагов назад путём повторения данного действия. Пре необходимости отказа от отката в меню рефакторинга следует выбрать пункт Redo.

Второй случай - перемещение элементов программы с одного места на другое.

Например, мы хотим переместить класс из одного пакета в другой. Для выполнения этого действия достаточно перетащить мышью в окне Projects узел, связанный с данным классом, в соответствующий пакет. При таком перемещении там, где это необходимо, автоматически добавляются операторы импорта.

Если при перемещении возникают проблемы, о них выдаётся сообщение. Как правило, проблемы бывают связаны с неправильными уровнями видимости. Например, если указан пакетный уровень видимости метода, он доступен другим классам этого пакета. А при переносе класса в другой пакет в месте исходного кода, где осуществляется такой доступ, в новом варианте кода возникает ошибка доступа. Перенос класса в отдельный пакет, отличающийся от пакета приложения – хороший способ проверить правильности выбранных уровней доступа для членов класса.

Аналогичным образом перемещаются пакеты. При этом все пакеты в дереве элементов показываются на одном уровне вложенности, но у вложенных пакетов имена квалифицируются именем родительского пакета.

Третий случай - инкапсуляция полей данных.

Напрямую давать доступ к полю данных – дурной тон программирования. Поэтому рекомендуется давать полям уровень видимости private, а доступ к ним по чтению и записи осуществлять с помощью методов getИмяПоля и setИмяПоля - получить и установить значение этого поля. Такие методы в Java называют геттерами (getters) и сеттерами (setters).

Но при введении в класс новых полей на первом этапе часто бывает удобнее задать поля с модификатором public и обеспечивать чтение значения полей напрямую, а изменение значения – путём присваивания полям новых значений. А затем можно исправить данный недостаток программы с помощью инкапсуляции полей данных. Это делается просто: в дереве элементов программы окна Projects в разделе Fields (“поля”) щёлкнем правой кнопкой мыши по имени поля и выберем в появившемся всплывающем меню Refactor/Encapsulate Fields… (“Провести рефакторинг”/ “Инкапсулировать поля…”).В появившемся диалоге нажмём на кнопку “Next>” и проведём рефакторинг. При этом каждое поле приобретёт модификатор видимости private, а во всех местах программы, где напрямую шёл доступ к этому полю, в коде будет проведена замена на вызовы геттеров и сеттеров.

Более подробную информацию по идеологии и методах рефакторинга проектов, написанных на языке Java, можно найти в монографии [7]. Правда, эта книга уже несколько устарела – среда NetBeans позволяет делать в автоматическом режиме многие из описанных в [7] действий.

Reverse engineering – построение UML-диаграмм по разработанным классам

Среда NetBeans при установленном пакете NetBeans Enterprise Pack позволяет по имеющемуся исходному коду построить UML-диаграммы. Для этого следует открыть проект и нажать на главной панели среды разработки кнопку

“Reverse Engineer…”

Кнопка “Reverse Engineering

Появится диалоговая форма задания параметров создаваемого проекта, в которой следует изменить название проекта на осмысленное, по которому легко можно будет определить, к какому проекту Java он относится.

Диалоговая форма задания параметров создаваемого UML-проекта

В нашем случае UMLProject7 мы заменим на UML_Figure. После нажатия на кнопку Finish (“Закончить”) будет выдана форма с ненужной вспомогательной информацией, и в ней следует нажать кнопку Done (“Сделано”). В результате чего мы получим новый UML-проект, в котором можно просмотреть параметры, относящиеся к каждому классу:

Параметры UML-проекта, относящиеся к классу Circle

Для класса показываются конструкторы и обычные методы (узел Operations), а также отношения наследования и другие варианты отношений (узел Relationships).

В UML-проекте можно сгенерировать UML-диаграммы, щёлкнув правой кнопкой мыши по имени соответствующего класса:

Всплывающее меню действий с классом в UML-проекте

Если выбрать пункт “Create Diagram From Selected Elements” (“Создать диаграмму из выбранных элементов”), и далее выбрать тип диаграммы “Class Diagram”,