UMLを学ぶETロボコンメンバーに送るUML講座4〜クラス図〜 

#内容アウトライン

・クラス図とは
・クラスの書き方
・クラス間の関連の種類
・まとめ

#クラス図とは
　クラス図とは、**システムの静的な構造を明確に表現するための図です**。
　実装に近づいてきた関係で、オブジェクト指向プログラミング言語の機能の片鱗が見えます。なので、それを想像しながらソースコードとどこが対応づけされているのかを考えながら勉強すると、吸収効率が上がると思います。

　構成要素としては、以下の２要素からなります。

・クラス
・クラス間の関連を表す線
　
　イメージとしては以下のようになります。

<img width="682" alt="スクリーンショット 2019-02-26 10.23.30.png" src="https://qiita-image-store.s3.amazonaws.com/0/219573/2326e427-f9b4-6aab-d73d-70482f96e71b.png">


　クラスは長方形で表現されます。横線２本で三等分にし、**一番上に「クラス名」、真ん中に「属性名」、一番下に「操作」を記述します**。

　**クラス間をつないでいるただの線を、関連と呼びます。**クラス間の関係を表す線には他にもたくさん種類があるので、それについては以下で書いていきます。

#クラスの書き方
###属性の書き方
　クラス名を上段に書いたら属性を中段に書きます。
　属性を表現する際に**何も省略しない場合の構文は以下の通り**になります

　**”可視性”  ”属性名”：”型” ＝ ”初期値”**

　ダブルクォーテーションで囲まれた部分が変化します。
　わかる通り、**属性の要素としては可視性、属性名、型、初期値があります**。

####可視性
　**可視性とは、アクセス制限のことを表現します**。
　プログラミング言語で言うところのpublicやprivate、protectedのことです。

　アクセスレベルを表現する記号は以下の通りです。

・「-」はprivate。自クラスからしかアクセスできない。
・「#」はprotected。自クラスとその子クラスはアクセス可能。
・「~」は同一パッケージ内からはアクセスできることを表現。packageと呼ぶ。
・「+」はpublic。どこからでもアクセス可能。


####属性名
　**属性名は、そのクラスがどういった情報を持つのかを表現する名前です**。

####型
　**型は、属性の情報をどういった形式で保持するかを表すものです**。

####初期値
　**初期値は、型に適合した具体的な値がなんであるかを表現します。**

####省略できるのは型と初期値
　属性を記述する際に省略できるのは、型と初期値です。
　**可視性、属性名は省略できません**。

###操作の書き方
　**ソースコードで言うところの関数に対応するのが操作です。**
　クラスの中で一番下の領域に書きます。
　操作の構文は以下のようになっています。

**”可視性” ”操作名”（”引数名”：”型”）：”戻り値の型”**

　ダブルクォーテーションで囲まれているところに名前に対応した文字を書き込みます。

####可視性
　これは先ほど属性の書き方で説明した可視性と全く同じ意味です。**どのクラスからならアクセスできるのか、ということを表現します**。

　なので、”可視性”に入る記号は「-」「#」「~」「+」のどれかです。
　
####操作名
　**クラス内部で大まかにどのような処理が行われるのかを表現したのが操作名です。**

####引数名
　**引数名とは、どんな何を受け取るのかを表現したものです。**

####型
　**型は、「：」を挟んで左隣の引数名がどういうデータ形式かを表すものです**

 例としては、「個数：整数」などです。
 なお、このように個数といえば大体離散的に１、２、・・・N個となるので、型を表記する必要性はあまりないように思います。

####戻り値の型
　**操作が利用された時に返すデータの形式を表現するものです**

戻り値と言う名の通り、ソースコードでいう`return`するものに当たります。

####補足と省略について
　**「”引数名”：”型”」は、「,」で列ねることができます**。

　**省略は「”引数名”：”型”」、戻り値の型は省略ができます。**
 
　なお、省略は求められる詳細度に合わせて変えましょう。
　


#クラス間の関連の種類
#### 汎化・特化の関係

汎化と特化の関係は抽象と具現の関係です。
ソースコード上では親クラスと子クラスの関係です。
つまりは継承ですね。

<img width="633" alt="スクリーンショット 2019-02-26 11.10.24.png" src="https://qiita-image-store.s3.amazonaws.com/0/219573/54525019-da4b-da85-3b9b-18cb2366fee6.png">


上記の図のように、表記は**白抜きの矢印で表現します**。矢印を指されているクラスが親クラスで、矢印を出しているクラスが子クラスです。

操作については省略しています。

気に入っている覚え方は、以下のものです。

>**「子クラスは親クラスを知っている必要があるが、親クラスは子クラスを知っている必要はない」**

子クラスは親クラスのメンバ及び関数を自身のメンバと関数にするために、親クラスのことを知っていなければなりません。この表現はそのようすをしっかりと表せていると思います。

#### 関連の詳細度UP　〜多重度と誘導可能性及び関連端名〜
クラス図はオブジェクト図と異なりクラス関係をさらに詳細に表現できなければなりません。
したがって、クラス図はクラス間の関係性を詳細に表現できるように以下の表記が用意されています。

- 多重度
- 誘導可能性
- 関連端名

まあ、多重度はオブジェクト図にもありますが……。

##### 多重度
多重度とは、**クラスとクラスの個数の関係を表現するもの**です。
関連線のある両端に記載されます。

<img width="557" alt="スクリーンショット 2019-02-26 11.39.30.png" src="https://qiita-image-store.s3.amazonaws.com/0/219573/8835135d-8b40-f30c-75c0-e141888fba5b.png">


本棚と本というクラスがあるとしましょう。本棚から本を見た場合、本棚に対して本がどのような値をとるのか示しているのは本の近く書かれている多重度です。

つまり、こういう風にみます。

<img width="634" alt="スクリーンショット 2019-02-26 11.45.28.png" src="https://qiita-image-store.s3.amazonaws.com/0/219573/8c69cb00-1973-8d19-11a4-ca5c1cf278ff.png">

上記図の例では、本棚クラスに対して本クラスが関連し、その多重度は一対0以上になっています。
本棚クラスが一つに対して、本は０以上の任意数になることを表しています。

本棚クラスから本を見ると、本棚一つに対して本は０以上関連しているという関係をしめしており、反対に、本クラスから本棚を見ると、本はただ一つの本棚に収容されることを表現しています。

その他の表現方法には以下のようのものがあります。

| 表現       |　取る値　|
|:-----------------|------------------|
| 1..＊             |一以上　|
| 1,3,7           |一か三か七か |
| 6..9             |六から九 | 
| 3..4               |三か四 |
| 4,6~8             |四または六から八 |

##### 誘導可能性
誘導可能性とは、**クラス同士の関連の仕方を表現するもの**です。
通常、ーーー何も修飾のない棒線の場合ーーー関連線は相互に利用し合うか、利用被利用の関係が定まっていないことを表現しています。

これではクラス同士の関係を詳細に表現するのには不適切と言えます。
クラス同士の関係には、片方から利用するだけの場合などもあるからです。
その時に、ただの関連線で表現しているとあらぬ誤解を招く可能性があります。

関連線の意味をまとめてみました。

| 図       |　その意味　|
|:-----------------|------------------|
| <img width="398" alt="スクリーンショット 2019-02-26 11.56.34.png" src="https://qiita-image-store.s3.amazonaws.com/0/219573/d7b13905-520e-d0e7-60e0-9437b7074617.png">|AとBは相互に利用する。または、利用、被利用の関係が定まっていない。　|
| <img width="376" alt="スクリーンショット 2019-02-26 11.56.48.png" src="https://qiita-image-store.s3.amazonaws.com/0/219573/a48fb331-e60c-a14e-9aae-5c7dd8992d99.png">|AからBを利用する。BからAを利用する可能性もないわけではない。|
|   <img width="383" alt="スクリーンショット 2019-02-26 11.56.58.png" src="https://qiita-image-store.s3.amazonaws.com/0/219573/5587ba68-4073-32ce-5abf-52665064101b.png">|AからBを利用するだけ。BからAは利用できない。 | 

なお、設計が詳細にするにつれて、誘導可能性は出来るだけ一方からの利用のみにして設計すべきです。相互に影響を与え合うような設計は修正や、変更の影響が1クラスのみにとどまらないので、修正変更に非常に苦労することになります。

このように、クラス同士の関係が薄いことを疎結合であると言います。

##### 関連端名
関連端名とは、**一方のクラスからみて関連しているクラスがどのような役割を果たしているのかを表現する**ものです。

<img width="644" alt="スクリーンショット 2019-02-26 16.11.44.png" src="https://qiita-image-store.s3.amazonaws.com/0/219573/69cc7756-b99a-843b-dc2c-f1e606c236bb.png">

本棚から見て、本は管理するものです。反対に、本から見て本棚は収納されるものです。


誤り訂正です。以下の文章は関連名についてでした。

~~注意してほしいのは、これらは一方から見た**総合的な関係**を表わさなければなりません。~~

~~僕は去年のETロボコンのモデルのクラス図で「カラーセンサを利用する」などというように利用する関数名をそのまま書いていました。~~

~~大会が終わった後にETロボコンの実行委員の方にモデルを相談する機会があったのですが、そこでそのことについて指摘されてしまいました。~~

~~曰く、「どんな役割を果たしているのか俯瞰的に名付ける必要がある」そうです（詳しくは覚えていませんがだいたいこんな感じのことをいってました）。~~

~~俯瞰して見た場合の関連の役割を書くのは難しいですが、気を付けていきたいところです。~~

#### 集約とコンポジション
集約とは、**部分と全体の関係を表すもの**です。

<img width="481" alt="スクリーンショット 2019-02-26 16.15.05.png" src="https://qiita-image-store.s3.amazonaws.com/0/219573/ec244670-127b-4630-9a1e-1d234a65017e.png">



**白抜きの菱形を全体を表すクラスに向けて書き、反対側には部分に当たるクラスを書きます**。

コンポジションとは、集約の一種で、**部分と全体の結びつきが強い状態を表現します。**
表記方法は、集約を書いた場合の菱形を黒で塗りつぶすことでコンポジションの表現になります。

<img width="479" alt="スクリーンショット 2019-02-26 16.15.15.png" src="https://qiita-image-store.s3.amazonaws.com/0/219573/e5daf9a6-d46b-9f15-f070-211e15f04341.png">


どのような時にコンポジションが使われるかというと、**全体に当たるクラスを削除するに伴って部分に当たるクラスが消滅するような場合**にはコンポジションが利用されます。
全体の生成に部分の生成が伴う場合も同様にコンポジションを利用します。

つまり、集約は全体に当たるクラスの削除/生成に伴って、部分に当たるクラスが削除/生成されない、とも言えます。

#### インターフェース
インターフェースとは、**クラスが実装しなければならない操作をまとめて定義した**ものです。
プログラムにおけるインターフェースと同じです。

クラス名の上にステレオタイプ（「<<”文字列”>>」であらわされるもの）`<<interface>>`を書くことで、それがインターフェースになります。

<img width="484" alt="スクリーンショット 2019-02-26 12.57.15.png" src="https://qiita-image-store.s3.amazonaws.com/0/219573/b876ba63-ab2b-9e2f-2c47-984302ee4db5.png">

インターフェースの指定は、UMLの汎化・特化の矢印と非常に似ています。
すなわち、白抜き三角が、ステレオタイプ`<<interface>>`が書かれたクラスに向けられ、棒線の代わりに点線になっています。

汎化・特化との表記上の違いは**実線か、点線かということ**と、**インターフェースクラスに`<<interface>>`と書くだけ**です。

覚え方も同じです。
「インターフェースを実装するクラスはインターフェースのことを知っていなければならず、インターフェースそのものは、インターフェースを実装するクラスのことを知らなくていい」、です。

#まとめ
長かったですが、なんとか書き終わった……。

・クラス図はシステムの静的な構造を表現するための図である。

クラス図は重要な項目なので、全体的に意味は押さえておいてもらえると幸いです。