순간을 기록으로

[JAVA] 제네릭2 본문

Development/JAVA

[JAVA] 제네릭2

luminous13 2021. 11. 29. 13:11

제네릭 클래스와 상속

제네릭 클래스도  일반 클래스처럼 상속이 가능하다.

 

class Box<T> {	
	...
}

class SteelBox<T> extends Box<T> {	// 제네릭 클래스의 상속
	...
}

제네릭 클래스 StellBox<T>는 제네릭 클래스 Box<T>를 상속한다. 

 

 

코드를 그림으로 표현하면 다음과 같다.

 

Box<String> sBox = new SteelBox<>("Simple");
Box<Integer> iBox = new SteelBox<>(123);

 

 

이런 상속 관계에서 객체를 만드는 코드는 다음과 같이 짤 수 있다.

 

 

따라서 제네릭 클래스의 상속은 다음 관계도 만족한다.

즉, SteelBox<Integer> 제네릭 타입(=매개변수화 타입)은 Box<Integer> 제네릭 타입을 상속한다고 말할 수 있다.

 

그렇다면 Box<Number> box = new Box<Integer>();도 성립할까? Number와 Integer가 상속 관계에 있다고 하더라도 Box<Number>와 Box<Integer>은 별개의 자료형이다.

 

와일드카드기반 메소드 정의

와일드카드 기반 메소드는 제네릭 메소드와 비교했을 때 기능적으로 같지만 더 간결한 장점이 있다.

 

// 제네릭 기반 메소드 
public static <T> void peekBox(Box<T> box)

// 와일드 카드 기반 메소드
public static void peekBox<Box<?> box)

제네릭 기반 코드는 T를 2번 써야되지만 와일드 카드 기반 메소드는 ?를 한번만 사용하면 된다.

 

와일드 카드를 사용하는 이유

메소드에 필요한 만큼만 기능을 허용하여, 코드의 오류가 컴파일 과정에서 최대한 발견되도록하기 위해서이다.

예를들어 outBox 메소드는 상자에서 꺼내는 기능만 허용되고 상장에 넣는 기능은 금지되어야 한다. 반대로 inBox 메소드는 상자에 넣은 기능만 허용되고 상자에서 꺼내는 기능은 금지해야한다. 와일드 카드를 이요한 상한, 하한 제한이 있어야 가능하다.

 

와일드 카드에 하한 제한(? extends )을 걸어 get 기능만 허용하자.

public static void outBox(Box<? extends Toy> box) {
	box.get();	// 꺼내는 기능 ok
    	box.set(new Toy());	// 넣는 기능 x
}

다음과 같이 매개변수를 선언하면 상자를 꺼내는 건 가능하지만 넣는 것은 불가능하다. box.set() 메소드를 호출 할 수 없기 때문이다. set 메소드를 호출할 수 없는 이유는 위 메소드의 매개변수 box에 Toy 인스턴스를 저장할 수 있는 상자만 전달된다는 사실을 보장할 수 없기 때문이다.

 

와일드 카드에 상한제한(? super)을 걸어 set 기능만 허용하자.

public static void outBox(Box<? super Toy> box, Toy n) {
	box.set(n);	// 넣는 것ok
    	Toy myToy = box.get();	//꺼내기 x
}

위와 같이 상한 제한을 하면 get 메소드 호출문에서 컴파일 오류가 발생한다. 이뉴는 반환형을 Toy로 결정할 수 없기 때문이다. 즉 get 메소드 호출에는 문제가 없지만 반환되는 값을 저장하기 위해 참조변수 형을 Toy로 결정했다는 사실에서 문제가 발생한다.

Comments