Выбор типа создаваемой диаграмы
можно получить диаграмму такого вида:
Диаграмма для класса Circle
При этом лучше заменить имя создаваемой диаграммы, например, на Circle Diagram. Переименование можно сделать и позже, щёлкнув правой кнопкой мыши по имени диаграммы и выбрав в появившемся всплывающем меню пункт Rename… (“Переименовать…”).
Если же выделить Circle,Dot,Figure, ScalableFigure, мы получим диаграмму наследования, которой можно дать имя Inheritance Diagram.
Диаграмма для классов Circle,Dot,Figure, ScalableFigure
Если для класса Circle во всплывающем меню выбрать пункт “Generate Dependency Diagram” (“Сгенерировать диаграмму зависимостей”), получим следующую диаграмму :
Диаграмма зависимостей для класса Circle
Пункт всплывающего меню Navigate to Source позволяет вместо диаграмм показывать редактор исходного кода.
На диаграммах можно добавлять в классы или удалять из них поля и методы, проводить переименования, менять модификаторы. Причём изменения, сделанные на любой из диаграмм, автоматически отражаются как на других диаграммах UML-проекта, так и в исходном коде проекта Java (это проектирование – Forward Enineering). И наоборот - изменения, сделанные в исходном коде Java, автоматически применяются к диаграммам UML (это обратное проектирование – Reverse Enineering).
В настоящее время работа с UML-проектами в NetBeans Enterprise Pack не до конца отлажена, иногда наблюдаются “баги” (мелкие ошибки). Но можно надеяться, что в ближайшее время недостатки будут исправлены.
- Наследование опирается на инкапсуляцию. Оно позволяет строить на основе первоначального класса новые, добавляя в классы новые поля данных и методы. Первоначальный класс называется прародителем (ancestor), новые классы – его потомками (descendants). От потомков можно наследовать, получая очередных потомков. Набор классов, связанных отношением наследования, называется иерархией классов. Класс, стоящий во главе иерархии, от которого унаследованы все остальные (прямо или опосредованно), называется базовым классом иерархии.
- Иерархия нужна для того, чтобы писать полиморфный код. Основные преимущества объектного программирования обеспечиваются наличием полиморфного кода.
- Поля отражают состояние объекта, а методы - задают его поведение.
- Чем ближе к основанию иерархии лежит класс, тем более общим и универсальным (general) он является. Чем дальше от базового класса иерархии стоит класс, тем более специализированным (specialized) он является.
- Каждый объект класса-потомка при любых значениях его полей данных должен рассматриваться как экземпляр класса-прародителя на уровне абстракций поведения, но с некоторыми изменениями в реализации этого поведения.
- Проектирование классов осуществляется с помощью UML-диаграмм.
- В Java подпрограммы задаются только как методы в каком-либо классе и называются функциями. Объявление в классе функции состоит из задания заголовка и тела функции (её реализации).
- Параметры, указанные в заголовке функции при её декларации, называются формальными. А те параметры, которые подставляются во время вызова функции, называются фактическими. Формальные параметры нужны для того, чтобы указать последовательность действий с фактическими параметрами после того, как те будут переданы в подпрограмму во время вызова. Это ни что иное, как особый вид локальных переменных, которые используются для обмена данными с внешним миром.
- Параметры в Java передаются в функцию всегда по значению. Передача по ссылке отсутствует. В частности, ссылки передаются в функции по значению.
- В Java имеются уровни видимости private (“частный”, “закрытый”), пакетный, protected (“защищённый”) и public (Общедоступный). Пакетный – уровень видимости по умолчанию для полей и методов, для задания остальных уровней используются модификаторы private, protected и public.
- Ссылка this обеспечивает ссылку на объект из метода объекта. Чаще всего она используется при перекрытии области видимости имени поля объекта формальным параметром функции.
- В классе-наследнике методы можно переопределять. При этом у них должен сохраняться контракт – в который входит весь заголовок метода за исключением имён формальных параметров.
- Можно задавать перегруженные (overloaded) варианты методов, отличающиеся сигнатурой. В сигнатуру входит только часть заголовка метода – имя функции, а также число, порядок и тип её параметров.
- Переменной некоторого объектного типа можно присваивать выражение, имеющее тот же тип или тип класса-наследника. В качестве фактического параметра функции вместо формального параметра некоторого объектного типа можно подставлять выражение, имеющее тот же тип или тип класса-наследника. Именно это правило обеспечивает возможность использования полиморфного кода.
- Для приведения типа используется имя типа, заключённое в круглые скобки – как и для преобразования типа. Но при преобразовании типа могут меняться содержимое и размер ячейки, к которой применяется данный оператор, а при приведении типа ячейка и её содержимое остаются теми же, просто начинают считать, что у ячейки другой тип.
- Проверка на то, что объект является экземпляром заданного класса, осуществляется оператором instanceof: if(figure instanceof Circle)...
- Возможна программная проверка точного соответствия объекта нужному типу с помощью ссылки на класс: if(figure.getClass()==Circle.class)... При этом для экземпляра класса-наследника Circle сравнение даст false, в отличие от экземпляра Circle.
- Оператор isInstance позволяет проверять, является ли тип объекта совместимым с классом, на который задана ссылка c: if(c.isInstance(figure))... При если класс, экземпляром которого является объект figure, является наследником класса c или совпадает с ним, сравнение даст true.
- Рефакторинг – изменение структуры существующего проекта без изменения его функциональности. Три наиболее часто встречающихся примера рефакторинга: 1) Переименование элементов программы – классов, переменных, методов. 2) Перемещение элементов программы с одного места на другое. 3) Инкапсуляция полей данных.
- С помощью средств Reverse Engineering можно создавать UML-диаграммы классов и зависимостей классов. Причём после создания UML-проекта, сопровождающего Java-проект, изменения, сделанные в исходном коде Java, автоматически применяются к диаграммам UML, и наоборот.
Типичные ошибки:
public static double factorial(int n)
Модификатор static помечает подпрограмму как метод класса. То есть позволяет вызывать метод через имя класса без создания объекта.
Напомним, что факториал натурального числа n – это произведение всех натуральных чисел от 1 до n :
Кроме того, 0! считается равным 1. Обозначение факториала в виде n! математическое, в Java символ “!” зарезервирован для других целей. Также написать подпрограммы вычисления факториала с другими типами возвращаемых значений:
public static long factorial_long(int n) и
public static int factorial_int(int n)
Сравнить работу подпрограмм при n=0,1,5,10,20,50,100. Объяснить результаты.