티스토리 뷰

반응형

제네릭스의 기본적 정의와 사용 이유, 방법에 대해서는 이전 포스팅을 참고  ☞ 제네릭스(Generics) - 1. 제네릭스 사용 방법

제네릭 클래스

 다시 제네릭스의 정의에 대해서 생각해보자, 제네릭스가 '타입 체크'를 위한 기능이라는 것은, 결국 그 클래스가 다양한 타입의 객체를 사용할 수 있다는 것이다. 예제로 들었던, ArrayList에 클래스 선언문을 한번 보자.

public class ArrayList<E>{
    (중략)
    public ListIterator<E> listIterator(int index) {
    (중략)
    public E next() {
    .
    .

 ArrayList의 클래스 선언문을 보면 제일 상단 클래스 이름 오른쪽에 <E>로 명시되어 있고, 클래스 내부에서 E를 사용하고 있는 것을 알 수 있다. E라는 것은 결국 어떤 타입의 객체가 사용될지 정해지지 않았고, '앞으로 객체를 만드는 사람이 어떤 타입을 쓸 지 정하라!'라는 뜻이다. '타입 변수(타입 매개변수)'는 알파벳 E(element) 이외에도, T(type) K(key) V(value)를 관습적으로 사용한다.

 결론적으로 말하면, 객체 생성시에 제네릭스를 쓰기 위해서는 클래스를 만든 개발자가 제네릭스를 명시해야 사용 할 수 있다는 것이다. 이렇게 제네릭스가 사용된 클래스를 '제네릭 클래스' 라고 한다.


제한된 제네릭 클래스

이제 제네릭 클래스를 선언하는 개발자의 입장이 되어보자.

class MyClass<T>{
    . . .
}

MyClass를 만든 개발자는 이 클래스의 객체가 어떤 '타입 변수'를 받을지는 객체를 만드는 개발자(사용자)가 정하도록 하였다. 하지만 이 클래스는 Number객체를 상속 받아 구현된 객체들(Integer, Long . . .)만이 정상적으로 작동 하는 클래스라고 가정해볼 때, 객체를 만든 사용자가 예상되지 않은 타입 변수를 넣는 과정을 제한 하기 위해 클래스 선언문을 아래와 같이 설정할 수 있다.

class MyClass2<T extends Number>{
    . . .
}

'extends'라는 키워드를 이용하여서 타입 변수가 Number클래스와 Number클래스의 자손들만 담을 수 있다는 제한이 생긴 것이다.


제네릭 클래스 사용시 주의사항

  • 타입 변수가 인터페이스를 구현한 객체로 제한하고 싶다고 하더라도 implements가 아닌 extends 키워드를 사용한다.
     class MyCalss<T extends MyInterface>{ ... }
  • 타입 변수가 클래스의 상속과 인터페이스의 구현을 모두 해야 한다면 &기호로 구분한다.
     class MyCalss<T extends Number & MyInterface>{ ... }




제네릭 클래스의 와일드카드 "?"에 대해서는 다음 포스팅 참고  ☞ 제네릭스(Generics) - 3. 와일드 카드 <?>

반응형
댓글