UML之修饰符
1.可见性修饰符
面向对象思想中有一个重要概念是封装,封装意味着对象中成员的“可见性”是不同的。这里的对象通常指类和包,而它们的可见性通过可见性修饰符进行定义。
在UML中,类对象成员的可见性修饰符有四种,其具体说明如下:
修饰符 | 可见性 | 说明 |
---|---|---|
+ | 公共 | 成员属性、行为、值能够被任何对象看到、引用或调用 |
- | 私有 | 成员仅能在当前类的实例内被访问 |
# | 保护 | 成员在当前类及其派生类的实例内被访问 |
~ | 包 | 同一包内的同级元素可访问 |
类成员的前三种可见性比较容易理解,它与面向对象的编程语言中的含义是一致的,而最后的“包可见性”要结合包进行理解,可以结合以下包的可见性描述一并进行理解。
包与可见性有着密不可分的关系,与包相关的可见性说明如下:
修饰符 | 可见性 | 说明 |
---|---|---|
+ | 公共 | 具有公共可见性的成员对所有可以访问当前包的内容的元素都是可见的 |
- | 私有 | 具有私有可见性的成员仅在当前包内可见 |
# | 保护 | 具有受保护可见性的成员对与拥有它的命名空间具有泛化关系的元素是可见的(在继承元素中可见)。不允许在包或由包直接拥有的元素上使用。包不支持泛化/专门化。 |
~ | 包 | 具有包可见性的成员在其最近的封闭包(假设任何中间拥有元素具有适当的可见性)内部是可见的。在其最近的封闭包或标记为具有包可见性的元素之外是不可见的。不允许在包或包直接拥有的元素上使用。 |
上述说明文字比较晦涩,难于理解,下面我们通过两个示例来进行理解。
先看下图示例,包pkg1包含有三个元素:公共类Book、私有对象myBook及子包pkg2。它们的可见性分别被定义为公共、私有和公共。也就是说在包pkg1之外,可以看到类Book和包pkg2,而看不到对象myBook,但在包pkg1之内,这三个元素相互之间则都是可见的。
而在实际应用中,情况远比上述示例复杂,假想有如下图所示的包pkg1及子包pkg2,它们又各自包含了一些元素,这些元素之间的可见性又是什么样的呢?
为了方便起见,我们用以下表格来说明各元素之间的可见性。表格第一行是主动尝试去看其他元素的发起者,表格第一列是被看元素,在表格中我们则分别用Y和N分别表示被看元素相对主动元素的可见或不可见。
主动元素/被看元素 | C1 | C2 | C3 | C4 |
---|---|---|---|---|
-C1 | - | N | N | N |
-C2 | N | - | Y | Y |
+C3 | Y | Y | - | Y |
C4 | N | N | N | - |
+a1 | Y | Y | Y | Y |
-a2 | N | N | Y | N |
~a3 | N | Y | Y | Y |
#a4 | N | N | Y | Y |
对位于包pkg1中的C1,它只能访问包pkg2中的公共元素,因而它可以看见类C3;同时由于C3的属性a1是公共的,因此C1也可以访问到a1。
对位于包pkg2中的类C2,由于C1是包pkg1中的私有元素,因而它看不到;C3是同一个包中的公共元素,所以对C2可见,类似地,C3的公共属性a1对C2也是可见的;C3的属性a3的可见性被声明为包可见,故而它对同一包中的C2是可见的;同一个包中的C4由于未定义可见性,因而它对C2不可见。
对位于包pkg2中的类C3,同样看不到pkg1中的私有元素C1;而同在包pkg2中的C2对它可见;属性a1、a2、a3、a4均是类C3的成员,故均对C3可见。
对位于包pkg2中的类C4,其他元素对它的可见性与对C2的可见性类似;不过由于C4是C3的继承类,因而C4还可以看见C3中的保护成员a3。
2.修改保护/只读(readOnly & query)
对象的属性除了可见性外,在有些场景下,它还需要具备防止被修改的特性。例如很多系统中都会存在有“用户”对象,在定义代表用户的类user时,它会包含有一些属性,其中代表用户姓名的name、出生日期的birthdate等属性,很显然在对象实例中这些属性一旦被赋值,就应当不允许再改变。为了达到此目的,通常可以将这些属性的可见性设定为私有的,但在对象内,依然可以改变这些属性的值,更有效的方法是在属性名后添加“{readOnly}”,它表示该属性一旦被赋值,将不可改变。
类似地,类的操作其实也可从是否修改属性值的角度分为两类,其中一类是仅通过对属性的计算返回一个值而不会去改变任何属性的值,这样的操作在UML中称作查询,这也可以通过在操作后添加“{query}”进行标示。
以下是一个使用{readOnly}和{query}的示例。
3.参数方向(in/out/inout/return)
操作参数可以指定它的传递方向,它有如下4个可能的修饰符:
In:参数值由调用者传入,操作结束后其值不变
Inout:参数值由调用者传入,再由操作传出,操作结束后其值可能发生变化
Out:参数值由操作传出
Return:作为返回值传递给调用者
上述说明应当比较容易理解,以下是使用这些符号的一个示例:
billcc( in CCN:String,
in owner:NameType,
inout debit:Currentcy,
out successFlag:Boolean
) return ReturnType
上述操作的前两个参数CNN和owner被指定为in参数,即它们在调用操作时应当被赋值且该操作不会改变它们的值;第三个参数debit被指定为inout参数,即在调用操作前它应当被赋值,调用操作后它的值可能被改变;第四个参数successFlag被指定为out参数,即调用操作前它的值无关紧要,操作不会使用它,但操作会在执行过程中设定它的值,并且在操作完成后可以取得其值。
上述操作也指定了返回值类型为ReturnType,它可用于表明操作失败的原因,例如没有发现卡号、I/O或者网络错误等等。需要说明的是,在面向对象的分析与设计中,这类错误更合适的做法是通过抛出异常进行处理。
参考文献:
1.《OCUP 2 Certification Guide_ Preparing for the OMG Certified UML 2.5 Professional 2 Foundation Exam》 Michael Jesse Chonoles
2.《OMG Unified Modeling Language (OMG UML) Version 2.5.1》
UML之修饰符的更多相关文章
- JAVA语言中的修饰符
JAVA语言中的修饰符 -----------------------------------------------01--------------------------------------- ...
- Java类访问权限修饰符
一.概要 通过了解Java4种修饰符访问权限,能够进一步完善程序类,合理规划权限的范围,这样才能减少漏洞.提高安全性.具备表达力便于使用. 二.权限表 修饰符 同一个类 同一个包 不同包的子类 不同包 ...
- iOS 方法修饰符
一.NS_DESIGNATED_INITIALIZER 用来修饰init方法,被修饰的方法称为designated initializer:没有被这个修饰的init方法称为convenience i ...
- C#基础回顾(一)—C#访问修饰符
一.写在前面的话 好久没有停下来总结自己,转眼间15年过去好些天,回首过去的日子,亦或失去,亦或所得!生活的节奏,常常让我们带着急急忙忙的节奏去追赶,也许这并不是每个人所期望的生活方式!于他人,于自己 ...
- 关于Java语言中那些修饰符
一.在java中提供的一些修饰符,这些修饰符可以修饰类.变量和方法,在java中常见的修饰符有:abstract(抽象的).static(静态的).public(公共的).protected(受保护的 ...
- C#基础知识八之访问修饰符
1. 类的访问修饰符 修饰符 访问权限 无或者internal 只能在同一个程序集中访问类 public 同一个程序集或引用该程序集的外部都可访问类 abstract或internal abstra ...
- java访问修饰符
了解面向对象思想的同学们,都知道"封装"这一基本特征,如何正确运用访问修饰符,恰恰能体现出封装的好坏. java访问修饰符有四个: 1)public:访问权限最高,其修饰的类.类变 ...
- java静态修饰符static的使用
class Person { private String name; private int age; /* * 假设每个Person对象的国籍都一样, * 那么每次调用都要赋值就会不合理. * 使 ...
- Scala访问修饰符(四)
Scala 访问修饰符基本和Java的一样,分别有:private,protected,public. 如果没有指定访问修饰符符,默认情况下,Scala对象的访问级别都是 public. Scala ...
- Java 修饰符
Java语言提供了很多修饰符,主要分为以下两类: 访问修饰符 非访问修饰符 修饰符用来定义类.方法或者变量,通常放在语句的最前端.我们通过下面的例子来说明: public class classNam ...
随机推荐
- HDU-ACM 2024 Day4
T1001 超维攻坚(HDU 7469) 三维凸包,不会. T1002 黑白边游戏(HDU 7470) 显然这道题没有一个固定的最优策略,所以只能 \(\text{dp}\) 决策. 可以倒着做,设 ...
- 宏定义define的用法
#define read(x) scanf("%d",&x); 这行代码是一个宏定义,使用了 C 语言中的 #define 指令.它的作用是定义一个名为 read 的宏,用 ...
- KubeSphere 社区双周报|2024.03.29-04.11
KubeSphere 社区双周报主要整理展示新增的贡献者名单和证书.新增的讲师证书以及两周内提交过 commit 的贡献者,并对近期重要的 PR 进行解析,同时还包含了线上/线下活动和布道推广等一系列 ...
- KubeSphere 社区双周报|2024.02.29-03.14
KubeSphere 社区双周报主要整理展示新增的贡献者名单和证书.新增的讲师证书以及两周内提交过 commit 的贡献者,并对近期重要的 PR 进行解析,同时还包含了线上/线下活动和布道推广等一系列 ...
- flink jobmanager 终止任务失败问题
flink jobmanager 终止任务失败问题 :root { --default-font: ui-sans-serif, -apple-system, BlinkMacSystemFont, ...
- RocketMQ 5.0 如何配置TLS加密传输?
本文作者:李伟,社区里大家叫小伟,Apache RocketMQ Committer,RocketMQ Python客户端项目Owner ,Apache Doris Contributor,腾讯云Ro ...
- RocketMQ Streams拓扑构建与数据处理过程
本文作者:倪泽,Apache RocketMQ committer.RSQLDB/RocketMQ Streams Maintainer 01 背景 RocketMQ Streams 1.1.0版本已 ...
- Java序列化之ProtoStuff
知识点: ProtoStuff 是将结构数据转为字节流进行序列化的,优点是占用空间小,速度快,缺点是可读性差. ProtoStuff 是基于 ProtoBuf 发展而来的. 本文不讲那么多背景,直接上 ...
- 论文发表汇款:SWIFT code跨境汇款 —— 如何向境外账号汇款
如何向境外账号汇款? 有以下几种方式: 对方开通中国金融产品账号或在中国有代理公司:如对方开通中国的银行卡,微信.支付宝,等等,这样其实就不属于跨境汇款了,外国的一些公司已经开设中国的金融产品和银行账 ...
- Nuxt.js 应用中的 build:error 事件钩子详解
title: Nuxt.js 应用中的 build:error 事件钩子详解 date: 2024/11/7 updated: 2024/11/7 author: cmdragon excerpt: ...