クラス図の記号の意味(とついでにPlantUMLでの書き方)

はじめに

個人用(という逃げ)なので使いそうな物だけ書いてます。 C++の物を書く前提で、勉強をしながら書いてもいるので概念の理解や内容を間違って書いている部分もあるかもしれません。
すみません……。

  • [更新]インターフェース、継承[2021/03/17]
  • [追加]名前空間、パッケージ[2021/03/17]
  • [追加]非表示、newpage、独自定義、クラス内クラス、関係の少し詳しい説明[2021/03/21]

開始と終了

これで囲った中にUMLを書いていく。

@startuml
/' ここにコードを書いていく '/
@enduml

コメント

/' 
 ブロックコメント
`/
' 一行コメント

コメントは行の始めにしかつけられない

class クラス 'この書き方はエラーになる

要素

図の四角で囲った部分の事。(クラスとかインターフェースとか)

class クラス

f:id:polteageist:20210312190814p:plain

interface インターフェース

f:id:polteageist:20210312190811p:plain

abstract 抽象クラス
  ' ""で囲ってもいい
abstract class "抽象クラスの別の書き方"

f:id:polteageist:20210312190817p:plain

enum 列挙型

f:id:polteageist:20210312190821p:plain

class hoge<<?, #FFFFFF>>で独自に定義もできる

class 構造体<<S, #4169E1>>
class 神クラス<<G, #FFD700>>

f:id:polteageist:20210321174739p:plain

属性と操作

属性は要素の二段目、操作は三段目。(属性はメンバ変数、操作はメンバ関数(の理解であってると思う))
操作属性バラバラの並びでもかっこの有無でどっちか勝手に判断してくれる。

先に定義した要素名 : 属性または操作

もしくは定義と一緒に(こっちのがわかりやすいと思う)

class 要素名{
 属性または操作1
 属性または操作2
 属性または操作3
}

(どう書いてもPlantUMLは反映してくれるけど)UMLの属性と操作の書式は以下の通り

属性名 ( 引数1: 型名, 引数2: 型名 ) : 返り値の型
操作名 : 型名 = 初期値

全部を総合するとこう

class hogeクラス{
 hogeクラス : メンバ変数1
 hogeクラス : メンバ関数1()
}
 'かっこの外で後から書いてもいい
hogeクラス : メンバ関数2(hikisu : int) : int
 '最後にメンバ変数を書いてもちゃんと二段目に配置される
hogeクラス : メンバ変数2 : int = 0

f:id:polteageist:20210312204111p:plain

可視性

アクセス制限の事。
(~は同一パッケージ内のクラスからアクセス可能ってことらしいけどC++じゃ使わないかな……??(importで使うかも))

class hogeクラス{
 +public
 -private
 #protected
 ~package private
}

f:id:polteageist:20210312214257p:plain

記号をそのままにしたいときはどこかにskinparam classAttributeIconSize 0を書く

skinparam classAttributeIconSize 0

class hogeクラス{
 +public
 -private
 #protected
 ~package private
}

f:id:polteageist:20210312214254p:plain

抽象と静的(と無理やり属性、操作にする方法)

抽象操作(仮想関数や純粋仮想関数)は頭に{abstract}を付けて斜体に、静的属性(静的メンバ変数)または静的操作(静的メンバ関数)は頭に{static}を付けて下線を付ける。 ({field}が付くとかっこ付きでも属性に、{method}が付くとかっこなしでも操作になる)

'skinparamも{}で一気にかける
skinparam{
 classAttributeIconSize 0
  'フォントを指定しないと日本語が変化しない
 DefaultFontName "MS Gothic"
}

class クラス名{
 {abstract}+抽象メンバ関数()
 '変数にも一応つけれる
 {field}{abstract}+抽象メンバ変数(?)
 {static}+静的メンバ関数
 {static}+静的メンバ変数
}

f:id:polteageist:20210312223202p:plain

関係

要素と要素の関係(依存や継承)は線と矢印で示します。

  • 実現(インターフェース)
interface インターフェース
class 具現クラス
インターフェース <|.. 具現クラス

' クラスの定義と一緒に書くこともできる
' この場合インターフェースの中身を別で定義しないといけない
class 具現クラス2 implements インターフェース2{
 +hoge
}
interface インターフェース2{
 +getHoge() : int
}

f:id:polteageist:20210317064340p:plain

  • 汎化(継承)
abstract 抽象クラス
class 具現クラス
抽象クラス <|-- 具現クラス

' 継承もクラス定義と一緒に書ける
' この場合、普通のクラスを継承したとみなされる
class 具現クラス2 extends 継承元クラス2

f:id:polteageist:20210317064217p:plain

  • クラス内クラス
class クラスA
class クラスB
クラスA +-- クラスB

f:id:polteageist:20210321091626p:plain

  • 依存(薄い関係性、引数で一時的に使うとか)
class クラスA
class クラスB
クラスA <.. クラスB

f:id:polteageist:20210313000620p:plain

  • 誘導可能性(あるクラスがそのクラスを持ってるなど)
class クラスA
class クラスB
クラスA <-- クラスB

f:id:polteageist:20210321091151p:plain

  • 集約(全体と部分、あるクラスがそのクラスをリストで持っているなど)
class クラスA
class クラスB
クラスA o-- クラスB

f:id:polteageist:20210312233839p:plain

class クラスA
class クラスB
クラスA *-- クラスB

f:id:polteageist:20210312234450p:plain

個々を大雑把に説明すると……

関係 説明
実現 インターフェースの実現
汎化 抽象クラスの具現
依存 メンバには持ってないけど関数などで一時的に使う場合(そのクラスの変更がその関数に影響を与えるかもしれないから)
誘導可能性 メンバなどでAクラスがBクラスを単体で持ってる
コンポジション リストなどでAクラスがBクラスを複数持っていて、Bクラスを値・ポインタ(Aクラス内で確保してdeleteするもの)で持ってる場合
集約 リストなどでAクラスがBクラスを複数持っていて、Bクラスをポインタ(外部から受け取るなど)・参照で持ってる場合

名前空間(とパッケージ)

set namespaceSeparator ??????を変更することでスコープ解決演算子を変更できる

' スコープ解決演算子を::に
set namespaceSeparator ::

namespace 名前空間1{
 class クラスA
 class クラスB
 ' 名前空間内なので指定なしで書ける
 クラスA <-- クラスB
}

' 色を指定することもできる
namespace 名前空間2 #0080C0{
 class クラスC
}

' 名前空間付きで宣言すると自動的に名前空間ができる
class 名前空間3::クラスD

' 名前空間を跨いで関係を繋げるには名前空間を指定しないといけない
名前空間3::クラスD --> 名前空間2::クラスC
名前空間3::クラスD --> 名前空間1::クラスB

f:id:polteageist:20210317070304p:plain

パッケージはデフォルトだと名前空間と同じスタイルで描画されるけどオプションで変更できる

' skinparamでスタイルを一気に指定できる
skinparam packageStyle node

package パッケージ1{
 class クラスA
}

' 色指定
package パッケージ2 #0080C0{
 class クラスB
}

' 直接スタイルを変更することもできる
package パッケージ3 <<Frame>> #D05000{
 class クラスC
}

f:id:polteageist:20210317072522p:plain

スタイル一覧

package Node <<Node>>{
 class dummy1
}
package Rectangle <<Rectangle>>{
 class dummy2
}
package Folder <<Folder>>{
 class dummy3
}
package Cloud <<Cloud>> {
 class dummy4
}
package Database <<Database>>{
 class dummy5
}

f:id:polteageist:20210317072729p:plain

非表示

hide empty membersを使うと空のメンバを非表示にできる

hide empty members

class クラスA

f:id:polteageist:20210321180030p:plain

新しいページ

'newpage'を書くとそれ以降新しいページに書き込まれる。

' 画像のdpiを変更
skinparam dpi 200
hide empty members

class クラスA
class クラスB
クラスA <-- クラスB

' hideなんかの設定はリセットされる
newpage

class クラスA
class クラスB
クラスA <-- クラスB

f:id:polteageist:20210321180533p:plain
f:id:polteageist:20210321180536p:plain

参考させていただいたサイト様

plantuml.com cacoo.com lecture.ecc.u-tokyo.ac.jp