3 분 소요

2023. 01. 17. 수업내용 정리

열거형, 인터페이스, 제네릭


열거형

  • 열거형(Enumeration Type)은 어떠한 것의 종류가 의미론적으로 참과 거짓이 아닌 두 개 이하로 나누어 지거나, 세 가지 이상으로 나누어질 때 사용한다.
  • 열거형의 명명법은 파스칼 케이스를 따르고, 클래스와 마찬가지로 그 자체가 타입이 된다.
  • 수동으로 객체화할 수 없고 열거형이 가지는 열거된 인자들이 그 값이 되는데, 이 때 이 값들은 정적이고 읽기 전용인 열거형 타입의 객체이다.
    public enum [열거형 이름]{
      [인자,...]?
    }
    
    • 열거형의 인자들은 콤마(,)로 구분하여 여러개 적을 수 있다.
    • 단, 인자들 간에 같은 이름을 가지는 것이 있어서는 안 된다.
    • 앞서 얘기 했듯이 인자들은 정적이며 읽기 전용이다.
  • 모든 열거형 인자는 정적임으로 프로그램 실행 중에 단 하나밖에 존재할 수가 없음으로 동등 비교(==)및 부등 비교(!=)를 한다. (사실 equals 써도 관계 없음)



열거형의 고급적 사용

  • 열거형 인자의 나열이 끝나고 세미콜론(;)을 적어, 열거형 타입에 대한 멤버를 직접 구성할 수 있다.(클래스 처럼)
  • 각 인자 뒤에 괄호((,))를 이용하여 생성자에 전달할 전달 인자를 전달해 줄 수 있다. 생성자가 매개 변수를 가지지 않는다면 주로 생략한다.





인터페이스

  • 상속(Inheritance) 관계가 클래스 간의 기능 확장에 중점을 뒀다면, 인터페이스(Interface) 구현(Implementation)은 어떠한 클래스로 하여금 이에 속성이나 특성 등을 부여하거나 기능상의 골조를 만들기 위해 사용한다.
  • 명명법은 기본적으로 파스칼 케이스를 따르다, 대문자I로 시작하게 하기도 한다.
    • I(명사), I(동명사), I(-able) 혹은 I 없이 (명사), (동명사), -able
  • 인터페이스가 가지는 모든 멤버 변수는 public이고 정적이고 읽기 전용일 수 밖에 없다.
  • 인터페이스가 가지는 모든 메서드는 public이고 (일반적으로)추상적이다.
  • 인터페이스가 가지는 메서드가 구현부를 가지게 하기 위해 아래와 같이 default 키워드를 이용할 수 있다.
    public interface [인터페이스 이름] {
        default [반환 타입 | void] [메서드 이름]{
            // 구현부
        }     
    }
    

    이 때, default는 메서드를 추상화하지 않겠다는 키워드이며 접근 제한자가 아님에 유의한다.





제네릭(Generic)

  • 제네릭(Generic)은 어떠한 타입 A가 다른 타입 B에 대한 멤버(변수, 메서드의 반환 타입, 매개 변수 타입 등)를 가지고 이 타입 B가 동적으로 변하여 A 타입을 다분화하지 않고 능동적으로 사용하기 위해 존재한다.
  • 단, 제네릭 타입은 기초 타입일 수 없음에 유의한다.
    public class MonsterBall<T extends Mob> {
      private T monster;
      
      public T getMonster(){
          return this.monster;
      }  
    
      public void setMonster(T monster) {
          this.monster = monster;
      }
    }
    
    • 위 클래스 MonsterBallT를 제네릭으로 가지는 클래스이고, 이 때 TMob 클래스(혹은 인터페이스)를 상속 받음을 강제한다.
    • 위 클래스에서 T는 가상의 타입이고 명명법은 T[파스칼 케이스]로 하는 편이다. (가령, TKey, TValue 등)
    • 특정 제네릭에 대한 클래스는 타입으로 사용할 수 있음으로 아래 처럼 변수의 타입으로 사용될 수 있다.
      MonsterBall<Wyvern> wmb = new MonsterBall<Wyvern>();
      
    • 위 객체화 연산에서 객체를 넘겨 받는 타입의 제네릭과 객체화 할 때의 제네릭이 같다면 객체화시의 제네릭 타입은 아래와 같이 생략 가능하다.
      MonsterBall<Wyvern> wmb = new MonsterBall<>();
      



    다이나믹 제네릭(Dynamic Generic)

  • 제네릭의 선언부가 아닌 곳에서(클래스 이름 뒤 말고) ? 특수 문자를 활용하여 그 타입이 정확히 정해지지 않은 타입에 대한 제네릭을 활용할 수 있다.
    MonsterBall<Wyvern> wmb = new MonsterBall<>();
    MonsterBall<? extends Mob> someMb = wmb;
    

    위 코드에서 변수 someMb는 그 타입이 정확히 지정되지 않았지만 Mob 클래스를 상속 받는(? extends Mob)제네릭 타입에 대한 MonsterBall 타입임으로 MonsterBall<Wyvern> 타입인 변수 wmb를 받을 수 있다.



멀티 타입 파라미터 제네릭(Multi-type Parameter Generic)

  • 멀티 타입 파라미터 제네릭은 어떠한 타입이 제네릭을 두 개 이상 가지는 것을 의미하며, 주로 HashMap 혹은 튜플 구현에 사용한다.
  • 튜플은 서로 다른 두 타입의 값을 쌍(pair)으로 가지기 위한 타입이다.
    • 3개 타입에 대한 값을 가지는 타입을 3-튜플(3-Tuple 혹은 Triple 혹은 Triplet이라 한다.) 그 이상은 잘 안 쓰는데 궁금하면 검색.



부가적인 이야기

  • 부모 타입의 변수가 자식 객체를 받을 수 있는 것을 다형성의 일환으로 보는 것처럼 원형이 부모 타입인 아형이 원형이 자식 타입인 아형의 부모처럼 작동하는 것을 공변성(Covariant)이라고 한다. 가령, Object[]String[]의 부모 타입으로 인식되고 이를 공변성을 가진다라고 한다. 하지만, 제네릭은 공변성(Covariant)을 가지지 않음으로 List<Object>List<String>의 부모라고 하지 않는다.
  • 단, 자바 컴파일러의 트릭으로, 제네릭이 공변성을 가지는 것처럼 작동할 수 있게 하는데, 이가 다이나믹 제네릭의 상속이다. 가령, List<? extends Object>List<String>의 부모인냥 작동할 수 있게 하는 것이다.
  • 반대로, List<? super String>의 꼴에서 이가 가지는 인자는 [String이 상속 받고 있는 아무 타입]으로, 위 extends와 반대의 의미이고 이를 반공변성(Contravariant)라고 한다.

태그:

카테고리:

업데이트:

댓글남기기