Слайд 1Программирование на Java
Тема 3.2 Отношения между классами и объектами
Слайд 2 Интерфейсы
Определение интерфейса:
[public] interface Имя [extends Имя1,
Имя2,…, ИмяN] { // объявления public abstract методов
//
и статических констант
}
Пример 1:
interface LineGroup
{ // по умолчанию public abstract
double getPerimeter();// объявление метода
}
interface Shape extends LineGroup
{ //int id; ошибка, если нет инициализации
//void method(){} ошибка, так как абстрактный
// метод не может иметь тела!
double getSquare(); // объявление метода
}
Слайд 3 Интерфейсы
Интерфейс это конструкция языка программирования Java, в
рамках которой могут описываться только абстрактные публичные (abstract public) методы
и статические константы (final static). То есть также, как и на основе абстрактных классов, на основе интерфейсов нельзя порождать объекты.
Все объявленные в интерфейсе методы автоматически трактуются как public и abstract, а все поля – как public, static и final, даже если они так не объявлены.
Интерфейсы обычно объявляются как public, потому что описание функциональности, предоставляемое ими, может быть использовано в нескольких пакетах проекта. Интерфейсы с областью видимости в рамках пакета могут использоваться только в этом пакете и нигде более.
Для более простой идентификации интерфейсов в большом проекте в сообществе разработчиков действует негласное соглашение о добавлении к имени интерфейса символа 'I', в соответствии с которым вместо имени Shape можно записать IShape.
Один интерфейс может быть наследником другого интерфейса (пример 1).
Класс, который будет реализовывать интерфейс Shape, должен будет определить все методы из цепочки наследования интерфейсов. В данном случае это методы getPerimeter() и getSquare().
Слайд 4 Интерфейсы
Реализация интерфейса:
[доступ] class ИмяКласса implements Имя1,
Имя2,…, ИмяN
{ /*код класса*/ }
Пример
2:
// реализация интерфейса
class Rectangle implements Shape
{ private double a, b;
public Rectangle(double a, double b)
{ this.a = a; this.b = b; }
//реализация метода из интерфейса
public double getSquare()
{//площадь прямоугольника
return a * b;
}
//реализация метода из интерфейса
public double getPerimeter()
{ return 2 * (a + b);}
}
Слайд 5 Интерфейсы
На слайде Имя1, Имя2,…, ИмяN – перечень
используемых интерфейсов. Класс, который реализует интерфейс, должен предоставить полную реализацию
всех методов, объявленных в интерфейсе. Кроме этого, данный класс может объявлять свои собственные методы. Если класс расширяет интерфейс, но полностью не реализует его методы, то этот класс должен быть объявлен как abstract.
Слайд 6 Интерфейсы
Пример 3:
// реализация интерфейса
class Circle implements Shape
{ private double r;
public Circle(double r)
{
this.r = r;}
public double getSquare()
{ //площадь круга
return Math.PI * Math.pow(r, 2);
}
public double getPerimeter()
{ return 2 * Math.PI * r;}
}
Слайд 7 Интерфейсы
Пример 4:
// неполная реализация интерфейса
// метод getSquare()
не реализован
abstract class Triangle implements Shape
{ private double
a, b, c;
public Triangle(double a, double b, double c)
{ this.a = a; this.b = b; this.c = c;}
public double getPerimeter()
{ return a + b + c; }
}
Слайд 8 Интерфейсы
Пример 5:
// свойства ссылки на интерфейс :
Runner.java
public class Runner
{ public static void printFeatures(Shape f)
{ System.out.printf("площадь:%.2f периметр: %.2f%n", f.getSquare(), f.getPerimeter());
}
public static void main(String[] args)
{ Rectangle r = new Rectangle(5, 9.95);
Circle c = new Circle(7.01);
printFeatures(r);
printFeatures(c);
}
}
Слайд 9 Интерфейсы
Класс Runner содержит метод printFeatures(Shape f), который
вызывает методы объекта, передаваемого ему в качестве параметра. Вначале ему
передается объект, соответствующий прямоугольнику, затем кругу (объекты с и r). Каким образом метод printFeatures() может обрабатывать объекты двух различных классов? Все дело в типе передаваемого этому методу аргумента – класса, реализующего интерфейс Shape. Вызывать, однако, можно только те методы, которые были объявлены в интерфейсе.
Слайд 10 Интерфейсы
Пример 6:
// динамический связывание методов : ShapeCreator.java
public class ShapeCreator
{ public static void main(String[] args)
{ Shape sh; // ссылка на интерфейсный тип
Rectangle re = new Rectangle(5, 9.95);
sh = re;
sh.getPerimeter();//вызов метода класса Rectangle
Circle cr = new Circle(7.01);
sh = cr; // присваивается ссылка на другой объект
sh.getPerimeter();//вызов метода класса Circle
// cr=re; ошибка! разные ветви наследования
}
}
Слайд 11 Интерфейсы
В примере 6 в классе ShapeCreator
используются классы и интерфейсы, определенные выше, и объявляется ссылка на
интерфейсный тип. Такая ссылка может указывать на экземпляр любого класса, который реализует объявленный интерфейс. При вызове метода через такую ссылку будет вызываться его реализованная версия, основанная на текущем экземпляре класса. Выполняемый метод разыскивается динамически во время выполнения, что позволяет создавать классы позже кода, который вызывает их методы.
Невозможно приравнивать ссылки на классы, находящиеся в разных ветвях наследования, так как не существует никакого способа привести один такой тип к другому. По этой же причине ошибку вызовет попытка объявления объекта в виде: Circle c = new Rectangle(1, 5);
Слайд 12 Интерфейсы
Пример 7: множественное наследование интерфейсов
Слайд 13 Интерфейсы
Java не поддерживает множественное наследование классов. Это
объясняется тем, что такое наследование порождает некоторые проблемы.
Чаще всего указываются
неоднозначности, возникающие при так называемом «ромбовидном» наследовании, когда один класс «A» является наследником двух других классов «B» и «C», которые в свою очередь оба являются наследниками класса «D». Проблема допустимости множественного наследования кроется в следующем. Предположим, что в родителе A определялся какой-то метод m1(). И этот же метод мы вызываем для объекта класса D. А что если m1() был переопределён в классах B и С. Какая реализация из трёх будет работать при вызове метода m1() для объекта класса D? От неодназначности можно было бы избавиться потребовав в описанном случае при вызове уточнять при вызове, какой из методов требуется (так и сделано в некоторых языках), но в Java от множественного наследования классов решили отказаться.
Вместо множественного наследования классов в Java введено множественное наследование интерфейсов, которое частично решает проблемы (но, как будет показано в примере далее, к сожалению, не все).
Рассмотрим пример, где реализовано два интерфейса с методами доступными для грузового и для легкового транспорта. Класс Pickup (пикап) должен обладать как возможностью перевозки грузов, так и пассажиров, поэтому он реализует сразу оба интерфейса.
Часто всю открытую часть класса (т. е. общедоступные методы) предопределяют как раз в интерфейсе. Тогда взглянув на один лишь интерфейс можно понять какие же методы должны использоваться для взаимодействия с объектами данного класса. То есть интерфейсы вполне соответствуют принципам инкапсуляции. Как, впрочем, и принципу полиморфизма. Ведь в нескольких классах метод некоторого интерфейса может быть реализован по-разному, хотя и с одним и тем же именем.
Слайд 14 Интерфейсы
Пример 8: множественное наследование интерфейсов
Слайд 15 Интерфейсы
Но интерфейсы, как говорилось выше, не
являются совершенным инструментом лишенным всяких недостатков. Рассмотрим пример, когда у
нас имеются два интерфейса, в каждом из которых есть свойства с одинаковыми именами (но, возможно, разными значениями) и методы с одинаковыми именами.
Унаследовав класс от пары этих интерфейсов мы не сможем обращаться к свойству его объектов напрямую, без указания того, какой из двух интерфейсов мы имели в виду. Это ограничение существует потому, что в интерфейсах свойствам может даваться разное начальное значение и, соответственно, программа не сможет определить какое же значение выбрать.
Также к свойству можно обратиться как к статическому свойству одного из интерфейсов (разумеется, это можно делать и если у свойств были бы разные имена).
Проблема исчезнет, если перед обращением к свойству мы приведём объект к одному из родительских интерфейсов (напомним, что любой объект можно явно привести к классу или интерфейсу его родителя прямого или транзитивного).
К сожалению, создать отдельные реализации для двух одноимённых методов из разных интерфейсов в классе наследнике не получится (чтобы потом ими можно было пользоваться через то же приведение объектов к нужному интерфейсу). Если класс реализует несколько интерфейсов, в которых есть одноимённые методы, то в нём может задаваться лишь одна общая для всех реализация этих методов (и это уже ограничивает полиморфизм при множественном наследовании через интерфейсы в Java).
Слайд 16 UML
UML: Строительные блоки
Сущности (Elements)
Отношения (Relationships)
Диаграммы (Diagrams)
UML: Сущности
Структурные
Поведенческие
Группирующие
Аннотационные
Слайд 17 UML
Моделирование программного обеспечения включает в себя этап
проектирования, который предшествует непосредственному программированию приложений. Создание модели позволяет получить
более точное понимание системы еще до ее разработки. Универсальный язык моделирования (UML) - как раз является одним из языков моделирования, который вы можете использовать для уточнения, визуализации и документирования моделей систем программного обеспечения, в том числе их структуры и схемы, в соответствии с требованиями.
Существует три вида строительных блоков UML: сущности - это абстракции; отношения объединяют эти абстракции друг с другом; а диаграммы группируют совокупность связанных сущностей посредством отношений.
Выделяют всего четыре типа сущностей (см. слайд).
Слайд 18 UML
Структурные сущности:
-Класс
- Интерфейс
-Кооперация
-Активный
класс
-Прецедент
(Use case)
- Компонент -Узел
Слайд 19 UML
Класс - совокупность объектов с общими атрибутами,
операциями, отношениями и семантикой. Графически класс обозначается в виде прямоугольника
с тремя полями: имя класса, атрибуты (свойства) класса и операции (методы) класса.
Интерфейс - совокупность операций, которые определяют сервис класса или компонента. Графически интерфейс также обозначается в виде прямоугольника с тремя полями: имя интерфейса, его атрибуты и операции. Над именем интерфейса дополнительно указывается слово "интерфейс" ("interface").
Кооперация - определяет взаимодействие и представляет собой совокупность ролей и других элементов, которые работают совместно для обеспечения кооперативного поведения, большего, чем сумма всех элементов. Графически кооперация обозначается в виде пунктирного эллипса.
Прецедент - описание последовательности действий, выполняемых системой для получения наблюдаемого результата, значимого для актера. Графически прецедент обозначается в виде эллипса, внутри которого указано имя прецедента.
Активный класс - класс, представители которого являются активными объектами и вовлечены в один или несколько процессов или потоков и могут инициировать деятельность по контролю.
Компонент - физическая заменяемая часть системы, которая соответствует и обеспечивает реализацию набора интерфейсов.
Узел - физический элемент, который существует во время выполнения программы и представляет собой вычислительный ресурс, обладающий некоторым объемом памяти и способностью обрабатывать данные.
Слайд 20 UML
Поведенческие сущности:
-Взаимодействие
-
Автомат
Поведенческие сущности:
Пакет
Аннотационные сущности:
- Примечание
Слайд 21 UML
Взаимодействие - состоит из набора сообщений, которыми
обмениваются объекты в рамках конкретного контекста для достижения определенной цели.
Автомат
- определяет последовательность состояний, через которые объект или взаимодействие проходят на протяжении своего жизненного цикла в ответ на различные события, а также его реакции на эти события.
Пакет - универсальный механизм организации элементов в группы.
Примечание - просто символ для обозначения комментариев, закрепленных за другими элементами или совокупностями элементов.
Слайд 22 UML
UML: Отношения:
Зависимость
Ассоциация
Слайд 23 UML
Зависимость - это семантическое отношение между двумя
сущностями, при котором изменение в одной сущности может оказать влияние
на семантику другой сущности. Стрелка показывает направление зависимости. На диаграмме MyClass1 находится в зависимости от MyClass2. Изменения в MyClass2 оказывают влияние на MyClass1.
Ассоциация - структурное отношение, описывающее совокупность связей между объектами. На каждом конце ассоциации может быть кратность, указывающая, сколько объектов должно соответствовать каждому объекту на противоположном конце ассоциации.
Ассоциация может быть направленной или ненаправленной. Ненаправленная ассоциация означает, что не было принято решение относительно направленности или двунаправленности ассоциации. На рисунке отображена ненаправленная ассоциация. Направленная ассоциация обозначается стрелкой.
Слайд 24 UML
UML: Отношения:
Агрегирование
Композиция
Обобщение
Реализация
Слайд 25 UML
Различают два типа ассоциаций: агрегирование и композиция.
Агрегирование отражает
отношение между целым и частью. Агрегирование обозначается на одном конце
ассоциации, в то время как второй конец остается немаркированным. На рисунке, Myclass2 является частью Myclass1.
Композиция также отражает отношение между целым и частью, но является более сильной формой агрегирования. Композиция обладает дополнительным ограничением - объект может быть частью только одного композита, а композит, в свою очередь, отвечает за время жизни всех своих составных частей - а именно, за их создание и уничтожение. На рисунке, MyClass1 не может существовать без MyClass2.
Обобщение - это отношение типа "родитель-потомок". MyClass2 - суперкласс (родитель), а MyClass1 - подкласс (потомок). На языке программирования Java, обобщение реализуется посредством дочерних объектов с использованием зарезервированного слова extends.
Реализация - это отношение между интерфейсом и реализованным классом. В языке Java реализация выполняется реализацией интерфейса с использованием зарезервированного слова implements.
Слайд 26 UML
UML: Диаграммы:
Диаграмма прецедентов
Диаграмма классов
Диаграмма пакетов
Диаграмма взаимодействий
Диаграмма состояний
Диаграмма деятельности
Диаграмма компонентов
Диаграмма
развертывания
Диаграмма компонентов
Слайд 28 UML
Диаграмма прецедентов отображает отношения между актерами и
прецедентами в пределах одной системы. Она помогает системному аналитику тщательно
продумать требования с точки зрения конечного пользователя. Диаграмма рисуется в виде графа актеров, совокупности прецедентов, заключенных в границы системы (прямоугольник), ассоциаций между актерами и прецедентами, и обобщения актеров.
Прецедент - набор сценариев для одной задачи или цели. Актер - это человек или система, которые инициируют события, присутствующие в задаче. В приведенной диаграмме прецедентов три актера: покупатель, администратор и служба кредитных карт. Эллипсы обозначают прецеденты (бизнес-процесс), а актеры обращаются к различным прецедентам. Связь между актером и прецедентами называется коммуникацией (общением). Прецедент "оплата кредитной картой" факторизован как отдельный прецедент и смоделирован с использованием отношения включения. Это означает, что другие прецеденты, которым необходимо взять оплату с покупателя, могут повторно использовать общий факторизованный прецедент "оплата кредитной картой". Граница системы отделяет систему от актеров и отображается прямоугольником "Сайт электронной коммерции".
Другими возможными вариантами отношений в диаграмме прецедентов являются: отношение расширения, которое указывает, что один прецедент является разновидностью другого и отношение обобщения, которое используется для отражения наследования среди прецедентов.
Слайд 30 UML
Диаграмма классов - это графическое представление статического
вида, отражающее совокупность статических элементов модели, например, классы, типы, и
их содержимое и отношения. Классы систематизированы в иерархии, обладающие общей структурой и поведением, и ассоциированы с другими классами. Диаграмма классов может содержать некоторые поведенческие сущности, например операции, но их динамические свойства обычно отражаются в других диаграммах, например в диаграммах состояний и диаграммах коопераций.
На диаграмме классов, приведенной на слайде, статическая структура описана вокруг главной сущности - Customer (покупатель), который связан с набором других классов, например Address (адрес), Order (заказ), и интерфейсом Payment (платеж). У покупателя может быть несколько Addresses (адресов) - (адрес доставки, расчетный адрес, дополнительный адрес доставки, и так далее) смоделированных агрегированием. Также у покупателя может быть отношение ассоциации с интерфейсом Payment (платеж) и классом Order (заказ). Интерфейс Payment (платеж) может быть либо CreditCard (кредитной картой) либо DebitCard (дебетовой картой), которые являются двумя реализационными моделями интерфейса Payment (платеж). У каждого заказа может быть много присоединенных OrderItems (предметов заказа). Так как OrderItem (предмет заказа) не может существовать без Order (заказ), то отношение смоделировано как композиция. PrivilegedCustomer (привилегированный покупатель) это особый Customer (покупатель), у которого есть скидки на сделанные покупки, и который является продолжением Customer (покупатель) на основе отношения обобщения. Навигация указывает направление перемещения по ассоциации. Кратность описывает возможные сущности.
Слайд 32 UML
Диаграмма пакетов отражает организацию систем в группах
и может рассматриваться как особый вид диаграммы классов. Классы группируются
в пакеты и обозначаются в виде прямоугольника с "закладкой" с правой стороны. Пунктирные стрелки отражают зависимости. В нижеприведенном примере три пакета: Customer (покупатель), Order (заказ), и ShoppingUI (номер покупки). Изменения в классах пакета Customer (покупатель) окажут влияние на классы пакета Order (заказ), и поэтому они отображаются отношением зависимости.
Слайд 33 UML
Диаграмма взаимодействий (последовательностей):
Слайд 34 UML
Диаграмма взаимодействий подчеркивает взаимодействие объектов,, наряду с
сообщениями, которыми объекты обмениваются. Диаграммы последовательностей и диаграммы коопераций являются
формами диаграмм взаимодействия.
Диаграмма последовательностей отображает взаимодействие в упорядоченном по времени виде. Таким образом, вы можете наблюдать за объектами - их жизненным циклом или сообщениям, которыми они обмениваются в хронологической последовательности.
В приведенной на слайде последовательности Administrator (администратор) инициирует последовательность, посылая сообщение createAccount(name,address) (создать счет(имя,адрес)) классу AccountManager (менеджер счетов) для создания нового счета покупателя. AccountManager (менеджер счетов) в свою очередь создает новый класс Account (счет) и, посылая сообщения, задает различные свойства класса, например setName(name) (задать имя(имя)) иsetAddress(address) (задать адрес(адрес)). В конечном итоге, возвращается вновь созданный объект Account (счет).
Сообщения отображаются стрелками, а жизненный цикл объекта - вертикальной линией, указывающей момент создания объекта и продолжительность его существования.
Слайд 35 UML
Диаграмма взаимодействий (коопераций):
Слайд 36 UML
Диаграмма коопераций отображает взаимодействие, организованное вокруг объектов, выполняющих операции.
Следовательно, она уделяет большее внимание структурной организации объектов, посылающих и
принимающих сообщения.
На приведенной на слайде диаграмме коопераций прямоугольники отображают объекты, а объекты обозначены следующим образом: "имя объекта: имя класса". У сообщений имеется порядковый номер. Первое инициирующее сообщение обозначено номером 1. Такие сообщения, как, например, create (создать) и setName() (задать имя()), снабжаются одинаковым десятичным префиксом для указания, что они являются частью одного запроса; а увеличивающийся суффикс указывает на очередность их появления.
Слайд 38 UML
Диаграмма состояний отображает автомат, включающий в себя
состояния, переходы, события и виды действий. Она предоставляет детальную картину
изменений состояния конкретного объекта. Состояние ссылается на значение, присвоенное конкретному атрибуту объекта и любые действия или побочные эффекты, возникающие при изменении значения атрибута.
В примере, приведенном на слайде, всего три состояния: Login (регистрация), Getting product name (получение названия продукта), и Catalog page (страница каталога), обозначенные прямоугольниками с закруглёнными углами. Стрелки обозначают переходы. Исходное состояние, обозначенное черным кружочком - фиктивное состояние для начала действия. События или условия инициирующие транзакцию указаны метками на стрелках. Из состояния Login (регистрации) приложение переходит в состояние Getting product name (получения названия продукта). Если продукт обнаружен (отражается условием [item found] (пункт найден)), то приложение переходит к Catalog page (странице каталога). С другой стороны, если продукт не обнаружен, то происходит переход в то же самое состояние. Конечное состояние обозначается концентрическим бело-черным кружочком.
Диаграмма состояний
Слайд 40 UML
Диаграмма деятельности является частным случаем диаграммы состояний,
в котором все или большинство состояний - это состояния деятельности
или состояния действия, и в котором все или большинство переходов инициируются завершением деятельности в исходных состояниях. Она используется для отражения перехода потока управления от одной деятельности к другой внутри системы, и, таким образом, для точного отображения последовательности выполняемых действий. Диаграмма состояний концентрирует внимание на объекте, подвергаемом процессу, тогда как диаграмма деятельности - на потоке деятельности, вовлеченном в одиночный процесс. Диаграмма является важной, потому что она акцентирует поток управления между объектами. Диаграммы деятельности можно считать усовершенствованной версией блок-схем.
В приведенном на слайде примере процесс начинается с фиктивного состояния, которое обозначено черным кружочком. Деятельности обозначены прямоугольниками с закругленными углами, а поток между деятельностями - стрелками. После деятельности Place order (размещение заказа), в результате который получены все необходимые данные, например адрес доставки и номер кредитной карты, переход разветвляется на две параллельные деятельности Prepare for shipping (подготовка к доставке) и Process billing (процесс оформления счета). В конечном итоге, обе параллельные деятельности объединяются в один переход и заканчиваются в фиктивном состоянии, которое обозначено концентрическим бело/черным кружочком. Ветвление и объединение обозначаются сплошной линией.
При разветвлении перехода, защитные выражения (например [isUrgent=true] и [isUrgent=false]) отмечают переходы. Пустые ромбы обозначают разветвление на несколько переходов и объединение в один переход.
Слайд 42 UML
Диаграмма компонентов отражает организацию совокупности компонентов и
существующие между ними зависимости. Они относятся к статическому виду реализации
системы и отражают зависимости между программными компонентами, включая компоненты исходного кода, компоненты двоичного кода, и исполняемые компоненты. Диаграмма компонентов обладает только дескрипторной формой; сущностной формы - нет.
В приведенном на слайде примере, компонент изображен в виде прямоугольника с двумя прямоугольниками, расположенными с левой стороны. Пунктирные линии со стрелками отражают зависимость между компонентами. Символ окружности обозначает интерфейс IProduct.
Слайд 44 UML
Диаграмма развертывания отражает конфигурацию обрабатывающих узлов системы
и размещенных в них компонентов, и относятся к статическому виду
архитектуры системы с точки зрения развертывания. Те компоненты, которые существуют в рабочем режиме, не отображаются на данном виде диаграмм. Они отображаются на диаграммах компонентов. Основное различие между диаграммой развертывания и диаграммой компонентов заключается в том, что первая отражает сущности, в то время как последняя отражает описание типов компонентов.
Куб обозначает узел, а ассоциативная связь отражает физическую связь между узлами. В приведенном ниже примере, узел DB2Server обозначает узел базы данных, в котором размещен компонент базы данных OrderDB. Доступ к данным происходит через IOrder интерфейс, обозначенный символом окружности. Компонент Web-контейнера находится в зависимости от IOrder, которая обозначена пунктирной линией со стрелкой.
Слайд 45 Контрольные вопросы
Интерфейсы: назначение, синтаксис описания и
примеры использования.
UML: отношение между классами обобщение и ассоциация и их
реализация в Java.
UML: отношение между классами зависимость и реализация и их реализация в Java.