UML 클래스 다이어그램을 사용하면 클래스 내부의 정적인 내용이나 클래스 사이의 관계를 표기할 수 있다. 클래스 다이어그램으로 클래스의 멤버 변수와 멤버 함수를 보여 줄 수 있으며 해당 클래스가 다른 클래스에서 상속되었는지, 다른 클래스를 참조하는지도 알 수 있다.
다시 말해, 소스코드에 나타나는 클래스 사이의 의존 관계를 모두 표기할 수 있다.
클래스는 단순한 사각형으로 그린다. 클래스 아이콘을 여러 구획으로 나눌 수도 있는데, 첫째 구획에는 클래스의 이름이, 둘째 구획에는 클래스의 변수, 셋째 구획에는 클래스의 메서드가 들어간다.
-
: private
#
: protected
+
: public
변수나 함수 인자의 타입은 저마다 자기 이름 뒤에 콜론을 찍고 적는다. 함수의 반환값도 비슷하게 함수 뒤에 콜론을 찍고 적는다.
public class Dialer {
public Vector digits;
private int nDigits;
public void digit(int n) { }
protected boolean recordDigit(int n) {
//...
}
}
클래스 사이의 연관은 대개 다른 객체의 참조(reference)를 가지는 인스턴스 변수를 의미한다. 화살촉 근처의 이름은 인스턴스 변수의 이름이다. 그리고 화살촉 근처의 숫자는 이 인스턴스 변수가 참조를 몇 개나 가질지 알려준다.
public class Phone {
private Button[] itsButtons[15];
}
*
는 여러 개를 뜻한다. Java에선 이런 연관을 Vector
나 List
또는 다른 컨테이너 타입으로 구현하는 경우가 자주 있다.
public class PhoneBook {
private Vector itsPnos;
}
UML에선 화살촉을 그릴 때 매우 주의해야 한다. 상속을 표현하는지 연관을 표현하는지 구분하기 힘들 수도 있다.
흔히 상속 관계를 세로로, 연관 관계를 가로로 그린다. UML에서 화살촉의 방향은 모두 소스코드 의존성의 방향이다. UML에서 상속 화살표는 기반 클래스(base class)를 가리킨다.
public class Employee { }
public class SalariedEmployee extends Employee { }
인터페이스와 실체화 관계는 다음과 같이 점선과 화살표로 표기한다.
public interface ButtonListener { }
public class ButtonListenerAdapter implements ButtonListener { }
클래스 스테레오타입은 보통 클래스의 이름 위에 놓인 길러멧 사이에 적는데, 앞서 <<interface>>
표기가 바로 이에 해당한다. Java 프로그래머가 사용할 만한 두 가지 스테레오 타입은 다음과 같다.
<<interface>>
: 이 스테레오타입이 붙은 클래스의 메서드는 모두 추상 메서드이므로, 어떤 메서드도 구현해서는 안된다. 그리고 interface 클래스는 인스턴스 변수를 가지지 못한다. 오직 정적 변수만 가질 수 있다. Java의 인터페이스에 정확히 대응된다.<<utility>>
: 이 클래스의 모든 메서드와 변수들은 정적이다. Grady Booch는 이를 흔히 클래스 유틸리티라고 불렀다.UML에서 추상 클래스나 추상 메서드를 표기하는 방법은 두 가지다.
{abstract}
프로퍼티를 사용한다.public abstract class Shape {
private Point itsAnchorPoint;
public abstract void draw();
}
public class B {
private int numB;
public int getNumB() {
return this.numB;
}
}
public class A {
private int numA;
// add 메소드가 반환한 이후에는 B 클래스의 b 객체는 제거된다.
public int add(B b) {
return numA + b.getNumB();
}
}
public class B {
private int numB;
public int getNumB() {
return this.numB;
}
}
public class A {
private int numA;
private B b;
// add 메소드가 반환한 이후에도 B 클래스의 b 객체는 여전히 남아 있다.
public int add() {
return numA + this.b.getNumB();
}
}
public class B {
private int numB;
public int getNumB() {
return this.numB;
}
}
public class A {
private int numA;
private B b;
public A(B externalB) {
this.b = externalB;
}
}
public class B {
}
public class A {
private B b;
public A(B externalB) {
this.b = new B();
}
}
UML에서 합성에 대한 정의에는 집합과 공통된 규칙 말고도 많은 항목이 들어 있다.
Java에서 객체 소멸은 GC가 수행하므로 어떤 객체의 수명을 관리할 필요는 거의 없다.