클래스 다이어그램

Class Diagram

  • 클래스의 구성요소 및 클래스 간의 관계를 묘사하는 다이어그램
  • 시간에 따라 변하지 않는 정적인 시스템 구조를 표현

클래스 다이어그램의 목적

  • 문제 해결을 위한 도메인 구조를 표현

Unified Modeling Language (UML)

  • 표준화된 모델링 표기 체계
  • 클래스를 구현하기 전에 설계하는 단계에서 사용
    • 클래스 이름, 파라미터, 리턴 타입 등

IDEA에서 UML 작성하기 (Plant UML)

  • Plant UML 플러그인 설치

  • Graphviz 설치 https://graphviz.org/download/

  • Plant UML의 문법

    • 클래스, 추상클래스, 인터페이스

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      interface IFoo {
      void method();
      }

      abstract class Bar

      class Foo {
      int [] array;
      int add(int x, int y);
      setArray(int [] array);
      void method();
      }
    • 가시성 (Visibility)

      • public : +
      • protected : #
      • default : ~
      • private : -
    • 클래스 간의 관계

      • Extension <|-
      • Aggregation o--
      • Composition *--
    • 타이틀

      1
      title 클래스 다이어그램 제목
    • 노트

      1
      2
      3
      note left of Foo
      노트 <b>내용</b> 작성
      end note

IDEA에서 UML 자동 생성

https://www.jetbrains.com/help/idea/class-diagram.html

Comment and share

제네릭 (Generic)

제네릭이란

  • 대상 객체의 타입을 입력받아 사용할 수 있는 형식
  • 미리 사용할 수 있는 타입을 명시하여 컴파일 타임에 체크할 수 있음
    • 입력을 Object로 한 경우 런타임을 체크하기 위한 instanceof를 많이 사용해야 함
    • 제네릭을 사용할 경우 간결하게 코드를 작성할 수 있다.

제네릭 클래스

제네릭 타입

  • 클래스와 인터페이스에 제네릭이 적용된 타입

  • 클래스를 선언할 때에는 타입이 알려지지 않으며, 타입 파라미터를 사용

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    public class GenericClass<T> { // T: 타입 파라미터
    ...
    }

    public interface GenericInterface<T> { // T: 타입 파라미터
    ...
    }

    public class HashMap<K,V> { // K, V: 타입 파라미터
    ...
    }
  • 제네릭 타입은 실제로 사용될 때 타입 파라미터에 자료형을 입력받는다.

    1
    2
    GenericClass<String> generic = new GenericClass<String>();
    GenericClass<String> generic2 = new GenericClass<>();

타입 파라미터 주의점

  • static 멤버 변수는 타입 파라미터를 사용할 수 없다.

  • 정적 메소드에도 타입 파라미터를 사용할 수 없다.

  • 이유 : 객체를 생성했을 때 타입 T가 결정되기 때문이다.

    1
    2
    3
    4
    public class Generic<T> {
    static T classVar; // not possible
    static void method(T localVar) {} // not possible
    }
  • new 키워드를 사용하여 객체 생성을 할 수 없다. - 안전성

    1
    2
    3
    public class Generic<T> {
    T var = new T(); // not possible
    }
  • instanceof의 피연산자로 사용할 수 없다. - 안전성

    1
    2
    3
    4
    5
    6
    7
    8
    public class Generic<T> {
    {
    Object obj = new Object();
    if(obj instanceof T) { // not possible
    ...
    }
    }
    }

제네릭 타입의 상속

  • 부모 클래스 또는 인터페이스에 선언한 타입 파라미터는 반드시 자식에서도 선언

  • 자식 클래스에서 추가적인 타입 파라미터 선언할 수 있다.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    class Foo<T> {
    ...
    }

    interface IBar<D> {
    ...
    }

    class FooBar<C, T, D> extends Foo<T> implements IBar<D> {
    ...
    }

파라미터 타입의 제한

  • extends를 이용하여 파라미터 타입을 제한할 수 있다.

    • 인터페이스의 경우에도 extends 키워드를 사용한다.
    • 클래스와 인터페이스를 동시에 제약하려면 &로 연결한다.
  • 제한한 자료형의 자식 클래스는 모두 사용할 수 있다.

    1
    2
    3
    4
    5
    6
    7
    class Generic<T extends Number> {
    ...
    }

    class Generic<T extends Number & Cloneable> {
    ...
    }

제네릭 메소드

메소드에 선언된 제네릭

  • 메소드의 리턴 타입 앞에 타입 파라미터 변수를 선언하여 사용

    1
    2
    3
    4
    5
    class GenericMethod {
    public <T> T method(T x) {
    return x;
    }
    }
  • 메소드에 선언된 제네릭은 정적 메소드에도 사용 가능

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    class GenericMethod<T> {
    public static void method(T t) { // Error
    ...
    }

    public static <P> P method (P p) { // Possible
    ...
    }

    public static <P, V> V methodA(P p){
    // Error : V Type Not Definition
    ...
    }
    }
  • 와일드카드

    • <?> => <? extends Object>와 동일
    • <? extends T> => 와일드카드의 상한을 제한, T 포함 상속 클래스
    • <? super T> => 와일드카드의 하한을 제한, T 포함 상위 클래스
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    class Foo {
    ...
    }

    class Bar extends Foo {
    ...
    }

    class Generic<T> {
    ...
    }

    class WildCard {
    public void method1(Generic<?> x) {}
    public void method2(Generic<? extends Foo> x) {}
    public void method3(Generic<? super Bar> x) {}
    }

Comment and share

열거형 (Enumeration)

열거형이란

  • 몇가지 한정된 상수로 표현될 수 있는 자료형을 구현
  • enum 키워드를 이용하며, 내부적으로는 java.lang.Enum 클래스를 상속

열거형의 특징

  • 접근 제한자는 publicdefault만 사용 가능
  • 다른 클래스를 상속받을 수 없으나, 인터페이스 구현은 가능
  • 열거형 타입에는 열거형 상수와 null 값을 할당할 수 있음

열거형의 구현

  • 일반적인 열거형의 구현

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    enum Job {
    STUDENT, MARKETING, DEVELOPER, CHIEF_EXECUTIONAL_OFFICER;
    }

    public class Main {
    public static void main(String[] args) {
    Job job = Job.STUDENT;

    if (job == Job.CHIEF_EXECUTIONAL_OFFICER) {
    System.out.println("사장님, 안녕하세요?");
    }

    switch (job) {
    case STUDENT: // case에서는 'Job.' 을 쓰지 않는다.
    System.out.println("You will be a great one.");
    break;
    case MARKETING:
    System.out.println("You make things sold.");
    break;
    case DEVELOPER:
    System.out.println("You usually don't go home.");
    break;
    case CHIEF_EXECUTIONAL_OFFICER:
    System.out.println("You choose your company's fate.");
    break;
    default:
    System.out.println("I don't recognize what you do.");
    }
    }
    }
  • 클래스 내부에서 열거형 구현

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    public class Foo {
    enum MyEnum {
    ONE, TWO;
    }
    }

    public class Main {
    public static void main(String[] args) {
    System.out.println(Foo.MyEnum.ONE);
    }
    }
  • 열거형에 메소드 구현

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    enum Symbol {
    ONE, TWO, THREE, FOUR;

    public Symbol nextSymbol() {
    if(this.equals(ONE)) {
    return TWO;
    } else if(this.equals(TWO)) {
    return THREE;
    } else if(this.equals(THREE)) {
    return FOUR;
    } else {
    return ONE;
    }
    }
    }

    public class Main {
    public static void main(String[] args) {
    Symbol sym = Symbol.ONE; // ONE
    Symbol nextSym = sym.nextSymbol(); // TWO
    nextSym = nextSym.nextSymbol(); // THREE
    }
    }

  • 열거형 생성자를 이용한 enum 상수 초기화

    • 열거형의 생성자는 항상 private이며 생략 가능
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    enum Family {
    FATHER("아버지"), MOTHER("어머니"), SON("아들"), DAUGHTER("딸"); // 생성자 호출
    private String koreanWord;

    Family(String koreanWord) { // private 생성자
    this.koreanWord = koreanWord;
    }

    public String getKoreanWord() {
    return koreanWord;
    }

    public void setKoreanWord(String koreanWord) {
    this.koreanWord = koreanWord;
    }
    }

    public class Main {
    public static void main(String[] args) {
    Family fam = Family.SON;
    System.out.println(fam.koreanWord) // 아들
    }
    }

Comment and share

인터페이스 (Interface)

인터페이스란

  • 클래스를 사용하는 방식, 접점만을 선언하는 클래스와 유사한 틀
  • 아무런 구현이 되어 있지 않으며, 모든 메소드가 추상 메소드

인터페이스의 특징

  • class가 아닌 interface 키워드로 선언

    • public 또는 default 접근 제어자만 사용 가능
  • 멤버 변수는 항상 public static final이며, 생략 가능

  • 멤버 메소드는 항상 public abstract이며, 생략 가능

  • 클래스와 달리 인터페이스는 여러 개 상속받을 수 있다.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    public interface IFoo {
    public static final int MEMBER_VAR = 10;
    int MEMBER_VAR2 = 20; // public static final

    public abstract void methodA(int param);
    void methodB(int param); // public abstract
    }

    public class Foo implements IFoo {
    @Override
    void methodA(int param) {
    System.out.println(param);
    }

    @Override
    void methodB(int param) {
    System.out.println(param);
    }
    }

인터페이스간의 상속

  • 인터페이스 간의 ‘IS-A’ 관계

  • 인터페이스가 인터페이스를 상속할 경우 extends로 상속

  • 클래스-클래스와 달리 다중 상속 가능

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    interface Walkable {
    void walk();
    }

    interface Runnable {
    void run();
    }

    public interface Jumpable extends Walkable, Runnable {
    void jump();
    }

    public class Jumper implements Jumpable {
    @Override
    void walk() {
    System.out.println("walk");
    }

    @Override
    void run() {
    System.out.println("run");
    }

    @Override
    void jump() {
    System.out.println("jump");
    }
    }

JDK 1.8

  • 기본 메소드 (Default method): 자식 클래스에서 구현할 필요가 없는 메소드

    • 인터페이스에 default 메소드를 구현할 수 있다.
    • default 메소드는 항상 public이다.
    • 인터페이스의 철학과 맞지 않으나, 인터페이스가 개선되었을 때 손쉽게 기능 추가를 위해 만들어짐
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    interface IFoo {
    void abstractMethod();

    default void defaultMethod() { // 구현 클래스에서 구현할 필요가 없다.
    System.out.println("Default method");
    }
    }

    class SuperFoo {
    void defaultMethod() {
    System.out.println("Super method");
    }
    }

    class FooOne implements IFoo {
    void abstractMethod() {
    return;
    }
    }

    class FooTwo extends SuperFoo implements IFoo {
    void abstractMethod() {
    return;
    }
    }

    public class Main {
    public static void main(String[] args) {
    FooOne fooOne = new FooOne();
    fooOne.defaultMethod(); // Default method

    FooTwo fooTwo = new FooTwo();
    fooTwo.defaultMethod(); // Super method
    }
    }
  • static 메소드: 클래스 메소드와 동일하게 사용 가능

    • 인터페이스 이름으로 호출 가능
    • 클래스 구현체의 이름으로도 호출 가능
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    interface IFoo {
    static void staticMethod() {
    System.out.println("static method");
    }
    }

    public class Main {
    public static void main(String[] args) {
    IFoo.staticMethod(); // static method
    }
    }

Comment and share

추상 클래스 (Abstract Class)

추상 클래스란

  • 일부 메소드가 구현되지 않고 선언만 되어 있는 클래스
    • 자식 클래스에서 반드시 구현해야 하는 메소드를 abstract로 선언
    • 필요한 모든 클래스가 구현될 수 있도록 강제

추상 클래스의 선언

  • abstract 키워드를 이용해 클래스를 선언

  • abstract 키워드를 이용해 메소드를 선언

    1
    2
    3
    4
    5
    6
    7
    abstract class AbstractFoo {
    public void method() {
    return;
    }

    public abstract void abstractMethod();
    }

Comment and share

  • page 1 of 1

Yechan Kim

author.bio


author.job