クラス図

クラス図はシステム内を構成するクラスとクラス間の関係を表します。 この図は特にオブジェクト指向に根付いた考え方なので オブジェクト指向を少しでも理解しておくと理解が進みます。

継承関係

継承とはメソッドやアトリビュートを引き継ぐことです。 それによって同じようなクラスを定義する必要がなくなります。 継承関係には次の関係があげられます。

それぞれ使用場面が異なります。

汎化

基底クラスでメソッドを実装して派生クラスで継承している状態です。 白抜き矢印と実線を使って表します。

Base <|- Special : 抽象化

ヒント

矢印の向きが直感的な継承関係と逆になっています。 それは派生クラス自身はどのクラスを継承しているかを知っていますが、 基底クラスはどのクラスに継承されているかを知らないことを表しています。

特化

基底クラスがI/Fや抽象クラスで、派生クラスでメソッドを実装する場合こちらを使います。 白抜き矢印と破線で表します。

Base <|. Special : 実現

ノート

多重継承の優先順位は表現できない?

PythonやC++などでは多重継承ができます。 多重継承する際にはスーパークラスの優先順位が非常に重要です。 優先順位によって有効なメソッドやアトリビュートが変わってしまうからです。 この多重継承の優先順位はUMLのクラス図ではどのように表現すればよいのでしょうか?

ノート

弁別子の違い

弁別子(つまり線)はノードに直接いくものと、 途中で他の弁別子と合流してからノードに行くものがあります。 この違いは 特化 の基準の違いにあります。 同じ基準(例えば性別や職業)での特化の場合は合流させます。 違う基準(例えば鉄と赤)での特化の場合は合流させません。 PlantUMLで表現できるのでしょうか?

ノート

弁別子の完全/不完全

全ての特化が列挙されている場合は完全、 そうでない場合は不完全といいます。

包含関係

集約

集約 は白抜きのひし形に実線で表します。次の例を見てください。

A o- B

この例ではAクラスの変数にBクラスのインスタンスがあることを表しています。 集約 の特徴はAのインスタンスが削除された時、 同時にBのインスタンスが削除されるとは限りません。

合成

合成 は黒塗りのひし形に実線を使います。次の例を見てください。

A *- B

この例ではAクラスの変数にBクラスのインスタンスがあることを表しています。 ここまでは 集約 と同じです。 合成 の特徴はAのインスタンスが削除された場合、 Bのインスタンスも削除されます。

その他の関係

依存

依存関係を示すこともできます。 クライアントサプライア に依存します。 サプライア が変更されると クライアント に影響します。 矢印と破線を使って表します。 矢印があるほうが サプライア です。

"クライアント" .> "サプライア" : 依存

複数に依存する場合は次のように書きます。

"サプライア1" <.. "クライアント" : 依存1
"サプライア2" <.. "クライアント" : 依存2

サプライア
依存される側
クライアント
依存する側

関連

関連はクラス間に何らかの関連性がある場合に使います。 意味合いが広いので、他の項目には含まれないが、関連性を示したいときに使います。 実線で表現します。 以下の図の場合AとBは何らかの関連性があります。

A - B

矢印を使うと関連性の方向を示すことができます。 矢印がない場合は双方向を表します。 以下の図はAからBへリンクをたどれる場合です。

class A
A -> B

多重度

包含関係関連 では 1対多または多対多の構成を組むことができます。 このそれぞれのインスタンスとそれが持つリファレンスの個数の表現を多重度といいます。 次のような図として表現します。

AAA "1" *-- "0..1" aaa : AAA1個に対しaaaが0個か1個
BBB "1" *-- "1"    bbb : BBB1個に対しbbbが必ず1個
CCC "1" *-- "0..*" ccc : CCC1個に対しcccが0個以上
DDD "1" *-- "*"    ddd : DDD1個に対しdddが0個以上
EEE "1" *-- "1..*" eee : EEE1個に対しeeeが1個以上

記号 意味
0..1 0個か1個
1 必ず1個
0..* 0個以上
* 0個以上
1.. 1個以上

可視性

プロパティやメソッドの可視性は以下の記号を使って表現できます。 プロパティやメソッドの前に該当する記号をつけます。 可視性は省略することも可能です。 初期の頃は省略しておいて実装前までに確定しておくと良いでしょう。

記号 意味
+ public
- private
# protected
~ package

class A {
     + public_attr
     - private_attr
     # protected_attr
     ~ package_attr
     + public_func()
     - private_func()
     # protected_func()
     ~ package_func()
     no_accessor_attr
}

public

全てのクラスからアクセスできます。 +記号で表します。 上記の図では次が該当します。

  • public_attr
  • public_func()

private

クラス自身からのアクセスのみ可能です。 クラス自身以外からのアクセスはできません。 -記号で表します。 上記の図では次が該当します。

  • private_attr
  • private_func()

protected

クラス自身とそのクラスを継承しているクラスからアクセスできます。 #記号で表します。 上記の図では次が該当します。

  • protected_attr
  • protected_func()

package

パッケージ内でアクセスできます。 パッケージの外からはアクセスできません。 ~記号で表します。 上記の図では次が該当します。

  • package_attr
  • package_func()

メンバーのバウンド

メンバーにはオブジェクトのどの状態に結合されているかで動作が代わります。 そのためUMLでもそれぞれ異なった書き方をします。 以下の図では次の対応のメンバーを表しています。

関数名  
instance_func() インスタンスメンバー
class_func() クラスメンバー
static_func() スタティックメンバー

class Spam {
     instance_func()
     {classifier} class_func()
     {static} static_func()
     }

ノート

ここではメソッドを取り上げていますがアトリビュートも同様です。

インスタンスメンバー

インスタンスに結合されたメンバーです。 例えばPythonのインスタンスメソッドでは メソッドの第一引数 self にインスタンスのリファレンスが渡される状態のものです。 通常はインスタンス化しなければ使うことができません。 UMLでは何も修飾しなければインスタンスメンバーとして扱われます。

クラスメンバー

クラスオブジェクト自体に結合されたメンバーです。 例えばPythonのクラスメソッドでは メソッドの第一引数 cls にそのクラスのリファレンスが渡される状態のものです。 クラスメンバーにはアンダーラインを引きます。

スタティックメンバー

クラスには属していますがどのオブジェクトにも結合されていないメンバーです。 例えばPythonのクラスメソッドでは メソッドの引数にインスタンスやクラスのリファレンスは渡されません。 スタティックメンバーにはアンダーラインを引きます。

純粋仮想関数

純粋仮想関数は斜体にして記述します。

class Spam {
    {abstract} virtual_func()
    normal_func1()
    normal_func2()
}

スポット

クラス定義は枠の一番上の円で囲まれた文字でそのタイプを表します。 これを スポット といいます。 一般的なものを紹介します。

ステレオタイプ

ステレオタイプ とは業務領域に特化した特定の意味のことです。 クラス名の隣に <<>> で括ることで表します。

class QueueManager <<S, #ff7700 Singleton>>

インターフェースクラスの表現

インターフェースクラスは インターフェースクラススポット を使った表現を紹介しました。 インターフェースクラスなどで継承目的でインターフェースを提供している場合 ロリポップを使って表現することもできます。 白抜き円に実線で表します。

VirtualIFClass ()- OnIFClass

ノート

インターフェースクラスを継承以外で利用する場合はこれを使えません

テンプレートクラス

テンプレートクラスを表すには <> で括ります。

class Ham <Spam:Class> {
}

名前空間

名前空間を表すには以下のようになります。

abstract class Spam
namespace bpy.ops #dddddd
    .Spam <|-- Ham

EatingIF o-- Person

.AbstractPerson <|-- EatingIF

end namespace


namespace bpy.spam {

    bpy.spam.Person <|-- Person
    .AbstractPerson <|-- Person
    bpy.spam.EatingIF o-- Person

}

AbstractPerson <|-- bpy.spam.Person

inserted by FC2 system