Возник вопрос по UML (диаграмма классов) — в чем разница между классами и атрибутами. На первый взгляд все просто — атрибут это характеристика объекта, являющаяся "простым" типом. Т.е. типом, состоящим из одного поля данных: дата, строка, число и т.п. Такие вещи пишем в атрибуты, что-то более сложное — как связь с другим классом.
Но как быть если атрибут является "простым" типом, но не стандартным? Возмем "День недели" — пусть это будет атрибут с возможными значениями от 1 до 7. Но при этом для него нужно определить и некоторые операции, сложения/вычитания например (смысл неважен, главное что нужны _какие-то_ операции). Вот как это изобразить в UML?
Или это все лишнее, и достаточно "нарисовать" его где-нибудь один раз в виде обычного класса, а дальше везде использовать как атрибут?
И еще, например вектор — это атрибут или объект? С одной стороны это не совсем простой тип, т.к. состоит из нескольких "координат", т.е. вроде и не атрибут. С другой — вполне логично иметь в виде атрибутов вектор скорости объекта, вектор силы тяжести и т.д... Так же возможны ситуации когда нужно задать нескольким объектам ссылки на один и тот же вектор (не одинаковые значения векторов, а именно один), т.е. тут вектор уже точно не может быть атрибутом...
Т.е. я к чему — можно ли в UML использовать "составные" атрибуты (для компактности), или все-таки в таких случаях всегда нужно рисовать объекты?
Здравствуйте, ObjectXplorer, Вы писали:
OX>Возник вопрос по UML (диаграмма классов) — в чем разница между классами и атрибутами. На первый взгляд все просто — атрибут это характеристика объекта, являющаяся "простым" типом. Т.е. типом, состоящим из одного поля данных: дата, строка, число и т.п. Такие вещи пишем в атрибуты, что-то более сложное — как связь с другим классом.
Никаких ограничений на тип атрибута не накладывается. Это может быть как простой, так и сложный тип. И не стОит сложный атрибут показывать как связь с другим классом.
OX>Но как быть если атрибут является "простым" типом, но не стандартным? Возмем "День недели" — пусть это будет атрибут с возможными значениями от 1 до 7. Но при этом для него нужно определить и некоторые операции, сложения/вычитания например (смысл неважен, главное что нужны _какие-то_ операции). Вот как это изобразить в UML?
OX>Или это все лишнее, и достаточно "нарисовать" его где-нибудь один раз в виде обычного класса, а дальше везде использовать как атрибут?
Так и отобразить, как ты предложил — отдельным классом для атрибута. Но в других классах он будет использоваться в качестве типа атрибута, никаких связей. Стереотип опять же никто не запрещает ввести если хочется акцентировать внимание на том, что это всего лишь атрибут, а не самостоятельный класс. Но какая в этом необходимость? По своей сути он ничем не отличается от обычного класса.
OX>Т.е. я к чему — можно ли в UML использовать "составные" атрибуты (для компактности), или все-таки в таких случаях всегда нужно рисовать объекты?
Составные объекты в качестве атрибутов использовать можно. Более того, если даже используется нестандартный тип атрибута (некий класс), то модель может и не содержать этот класс.
UML — это всего лишь язык моделирования и часто модель является неполной. Это нормально.
Здравствуйте, Буравчик, Вы писали:
Б>Никаких ограничений на тип атрибута не накладывается. Это может быть как простой, так и сложный тип. И не стОит сложный атрибут показывать как связь с другим классом.
А вот интересно — использование одного и того же класса и как атрибута, и как объекта — это нормально? Т.е. в большинстве случаев как атрибут, а когда нужно привязать одно значение атрибута к нескольким классам — как отдельный класс изобразить? Т.е. как-то вот так :
имея ввиду что и "Велосипед" и "Велосипедист" ссылаются на _один и тот же_ вектор скорости? А когда велосипедист падает, уже так:
Велосипед
---------------
Вектор скорости
Велосипедист
---------------
Вектор скорости
т.к. скорости у них уже разные
Т.е. вопрос в итоге сводится к тому, есть ли между атрибутами и классами принципиальная разница, или они могут свободно "перетекать" друг в друга в зависимости от конкретной ситуации?
Здравствуйте, ObjectXplorer, Вы писали:
OX>А вот интересно — использование одного и того же класса и как атрибута, и как объекта — это нормально? Т.е. в большинстве случаев как атрибут, а когда нужно привязать одно значение атрибута к нескольким классам — как отдельный класс изобразить? Т.е. как-то вот так :
OX>"Велосипед" --> "Вектор скорости" <-- "Велосипедист"
Использовать класс на одной диаграмме как атрибут, а на другой как отдельный класс — нормально. Но в представленном случае не нормально
OX>имея ввиду что и "Велосипед" и "Велосипедист" ссылаются на _один и тот же_ вектор скорости? А когда велосипедист падает, уже так:
OX>Велосипед OX>--------------- OX>Вектор скорости
OX>Велосипедист OX>--------------- OX>Вектор скорости
OX>т.к. скорости у них уже разные
Вот так нормально. Но лучше бы "вектор скорости" был для них всегда разным объектом, для которого определена операция "равно".
OX>Т.е. вопрос в итоге сводится к тому, есть ли между атрибутами и классами принципиальная разница, или они могут свободно "перетекать" друг в друга в зависимости от конкретной ситуации?
Диаграмма классов описывает статическое состояние, структуру. Атрибуты и классы во времени не могут "перетекать" друг в друга. Или я не понял вопрос.
Здравствуйте, Буравчик, Вы писали:
Б>Вот так нормально. Но лучше бы "вектор скорости" был для них всегда разным объектом, для которого определена операция "равно".
OX>>Т.е. вопрос в итоге сводится к тому, есть ли между атрибутами и классами принципиальная разница, или они могут свободно "перетекать" друг в друга в зависимости от конкретной ситуации?
Б>Диаграмма классов описывает статическое состояние, структуру. Атрибуты и классы во времени не могут "перетекать" друг в друга. Или я не понял вопрос.
Пускай не во времени, смысл в том, что если для того же велосипеда и велосипедиста вектор скорости будет отдельным атрибутом с операцией "равно", то при изменении их общей скорости нужно синхронно менять два атрибута, и на диаграмме это вроде бы только комментариями изобразить можно. А если вместо этого в данном конкретном случае изобразить вектор не в виде атрибута, а в виде объекта — то сразу понятно что этот вектор для них общий.
Хм.. А вот тут похоже и проявляются концептуальные различия атрибутов и классов... Т.к. атрибут принадлежит только одному объекту и для других недоступен (кроме как через операции самого объекта) — операции изменения ему в принципе не нужны (если только из соображений производительности, подразумевается что атрибут — это просто данные, без внутреннего состояния), достаточно присваивания нового значения. В случае с классом на него могут ссылаться другие объекты, т.е. нужны уже операции изменения состояния.
Получается вектор как атрибут будет иметь конструктор с координатами и оператор присваивания, а вектор как класс — конструктор по умолчанию и операции установки/изменения каждой координаты. Если же мы хотим использовать его и как атрибут, и как класс — получится некая комбинация того и другого, что выглядит не очень хорошо... Наверно лучше все-таки выбрать что-то одно — либо атрибут, либо класс.
Плюс атрибуту нужен конструктор копирования, если его планируется возвращать из функции, а для класса лучше использовать ссылку/умный указатель, копирование большей частью наоборот не нужно, а иногда и просто вредно.
Интересный вывод из всего этого получается: в случае с Си++ для атрибута вполне достаточно дефолтного конструктора копирования (т.к. никаких связей у атрибута быть не может — просто копируем поля данных), а для класса нужно "отключение" конструктора копирования и использование умных указателей. Хотя и то и другое будет описано как class — но разница налицо.