クラス図とは何か
クラス図は「オブジェクト指向の設計図」です。
クラス(型)の名前、持っているデータ(フィールド)、できること(メソッド)、そしてクラス同士の関係(関連・継承・依存など)を「箱と線」で表します。
Java のコードをそのまま読むと細かい実装で頭がいっぱいになりがちですが、クラス図はそれをギュッと要約して「このシステムには、どんなモノがいて、どうつながっているのか」を一目で見えるようにしてくれます。
クラス図の基本構造(1つのクラスをどう描くか)
クラスの箱の3段構成
クラス図では、1つのクラスを「3段の箱」で描きます。
一番上の段はクラス名。
真ん中の段はフィールド(属性、状態)。
一番下の段はメソッド(操作、振る舞い)。
Java コードと対応させるとイメージしやすいです。
public class User {
private String id;
private String name;
public String id() { return id; }
public String name() { return name; }
}
Javaこれをクラス図で表すと、頭の中ではこんなイメージになります。
User
——————
id : String
name : String
——————
id() : String
name() : String
実際のツールだと四角い箱で描かれますが、構造としては「名前/フィールド/メソッド」の三段、これだけ覚えれば十分です。
可視性(public / private など)の簡単な読み方
クラス図では、フィールドやメソッドの前に記号を付けて可視性を表すことが多いです。
「+」は public
「-」は private
「#」は protected
Java の修飾子とそのまま対応しています。
初心者のうちは「とりあえず + が外から使えるものなんだな」くらいの理解で大丈夫です。
関連(クラス同士の“線”)の基本
「知っている」関係としての関連
クラス図でクラスとクラスを線で結ぶとき、それは「関連(Association)」と呼ばれます。
意味はとてもシンプルで、「このクラスは、あのクラスを知っている(参照している)」という関係です。
Java で言えば、フィールドに別のクラス型を持っているとき、その2つの間に関連があると考えられます。
public class Address {
private String city;
}
public class User {
private String name;
private Address address; // User は Address を“知っている”
}
Javaこの場合、「User と Address の間に関連がある」と言えます。
クラス図では User と Address の箱を線で結びます。
多重度(1 対 1、1 対 多など)
関連の線には「多重度」という情報を付けることができます。
これは「片方から見て相手が何件か」を表します。
例えば「ユーザ 1 人に、住所 1 つ」なら 1 対 1。
「記事 1 つに、コメントが 0 個以上」なら 1 対 多。
Java 側では、1 件ならただのフィールド、複数なら List や Set などのコレクションで表現します。
public class Comment {
private String message;
}
public class Post {
private String title;
private List<Comment> comments; // 1 対 多(Post から見て Comment が複数)
}
Javaクラス図では、Post と Comment の間に線を引き、Post 側には「1」、Comment 側には「*」(多)と書いたりします。
継承(一般化)の表し方(重要)
「is-a」の関係を表す矢印
クラス図では、継承(一般化/特殊化)を三角形付きの矢印で表します。
Java で言う extends に対応します。
public abstract class Animal {
public abstract void speak();
}
public class Dog extends Animal {
@Override
public void speak() { System.out.println("wan"); }
}
Javaこの場合、「Dog は Animal の一種」なので is-a 関係です。
クラス図では Dog から Animal に向かって、空の三角形を付けた矢印を引きます。
Dog ─────▷ Animal
(実際の図では、矢印の先に白抜きの三角形が付きます)
ポイントは、「三角形の先が“親”」「根本側が“子”」という向きです。
多重継承は Java ではできないので、基本的に矢印は一本だけです。
インターフェースの実装も同じように描ける
インターフェースの implements も、クラス図では継承に近い形で描きます。
実装クラスからインターフェースへ三角形付きの線(普通は点線)を引くことが多いです。
public interface Formatter {
String format(String raw);
}
public class UpperFormatter implements Formatter {
@Override
public String format(String raw) {
return raw == null ? "" : raw.toUpperCase();
}
}
Javaクラス図上では「UpperFormatter ──▷ Formatter」という感じになります。
「UpperFormatter は Formatter を実装している」という意味です。
集約・コンポジション(“含む”の強さ)をざっくり理解する
クラス図では、「ただ知っている」だけでなく「一部として持っている」ニュアンスを表すために、
集約(◇)やコンポジション(◆)という記号を使うことがあります。
集約(◇):ゆるめの「全体と部分」
集約は「全体と部分」だけど、ライフサイクル的にはそこまで強くない関係です。
例えば「クラス(学級)と生徒」のようなイメージです。
クラスが無くなっても、生徒は別のクラスに移るなど、単独で生きていけそうな関係です。
コンポジション(◆):強めの「全体と部分」
コンポジションは「全体がなくなったら部分も一緒に消える」ような、強い全体と部分の関係です。
例えば「注文と注文明細」「家と部屋」などが例になります。
Java 的にはどちらもフィールドで表現されますが、
「設計としてどこまでを一つのまとまりにするか」を考えるときのヒントになります。
初心者のうちは、
「とりあえず、クラスが別のクラスをフィールドで持っているときは“関連”」
くらいの理解で十分で、
「それが設計上、ひとまとまり(集約)としたいのか?」を少しずつ意識していけばOKです。
Java コードとクラス図を対応させて考える練習
例題 1: ユーザと住所
public class Address {
private String city;
private String street;
}
public class User {
private String id;
private String name;
private Address address;
}
Javaクラス図で見ると、
User
——————
id : String
name : String
address : Address
Address
——————
city : String
street : String
User と Address は線で結ばれ、「User は Address を 1 つ持っている」関係になります。
例題 2: ブログとコメント、フォーマッタ
public interface Formatter {
String format(String raw);
}
public class UpperFormatter implements Formatter {
@Override
public String format(String raw) {
return raw == null ? "" : raw.toUpperCase();
}
}
public class Comment {
private String message;
}
public class Post {
private String title;
private List<Comment> comments;
private Formatter formatter;
}
Javaクラス図目線だと、
Post は Comment を「複数」持っている(1 対 多)。
Post は Formatter を「1 つ知っている」(関連)。
UpperFormatter は Formatter を実装している(継承矢印)。
という構造になります。
この「箱と線」に慣れてくると、
コードを見る前に「どういう世界観のシステムなのか」が頭に入りやすくなります。
重要ポイントのまとめ(クラス図を武器にする)
クラス図の基礎で押さえておきたいのは、次のようなところです。
クラスは「名前/フィールド/メソッド」の 3 段構成で描く。
関連の線は「このクラスが、あのクラスをフィールドとして持っている」ことを表す。
多重度(1、0..1、* など)は「何件つながるか」のルールを表す。
継承(extends/implements)は三角矢印で「is-a」を表す。
集約・コンポジションは「どこまでをひとまとまりにするか」という設計の強さの違い。
クラス図は「コードそのものを全部描くためのもの」ではなく、
「世界観と関係性をざっくり把握するための地図」です。
