CH12-9~11 제한된 지네릭 클래스, 지네릭스의 제약

[자바의 정석 - 기초편] ch12-9~11 제한된 지네릭 클래스, 지네릭스의 제약

지금까지 배운 지네릭 클래스의 타입변수에는 제약이 없었다. 하지만 제약을 걸 수 있는 문법이 있다.

Untitled

위처럼 타입변수에 extends 키워드를 사용하면, 해당 타입의 자손타입만 생성시 타입대입이 가능해진다.

여기서 좀 특이한게, 인터페이스인 경우에도 extends를 사용한다. implement를 사용하지 않는다.

타입의 매개변수화인데, 타입을 이제 유동적으로 선택할 수 있게 되었으므로 여기에도 상속 개념을 도입한다.

실습해보자.

import java.util.ArrayList;

class Fruit implements Eatable {
	public String toString() { return "Fruit";}
}
class Apple extends Fruit {
	public String toString() { return "Apple";}
}
class Grape extends Fruit {
	public String toString() { return "Grape";}
}
class Toy  {
	public String toString() { return "Toy";}
}
interface Eatable {}

public class EX12_3 {

	public static void main(String[] args) {
		FruitBox<Fruit> fruitBox = new FruitBox<Fruit>();
		FruitBox<Apple> appleBox = new FruitBox<Apple>();
		FruitBox<Grape> grapeBox = new FruitBox<Grape>();
		FruitBox<Toy> toyBox = new FruitBox<Toy>(); // 에러
	}

}

class FruitBox<T **extends Fruit & Eatable**> extends Box<T> {}

class Box<T> { 
	ArrayList<T> list = new ArrayList<T>();
	void add(T item) {list.add(item);}
	T get(int i)     {return list.get(i);}
	int size() 		 {return list.size();}
	public String toStrong() {return list.toString();}
}

위 코드는 인터페이스 Eatable을 상속받은 Fruit클래스를 상속받은 Apple과 Grape, 그리고 그냥 독립적인 클래스인 Toy를 작성했다.

이후 제네릭 클래스 박스와, 박스를 상속받으면서 타입변수로 Fruit과 Eatable만 받도록 제한한 클래스 FruitBox를 작성했다.

참고로 위에서는 Fruit이 Eatable을 이미 구현한 클래스라 Fruit만 적어도되는데, &사용법을 알려주기 위해 일부러 적었다.

Untitled

FruitBox클래스의 타입변수로 Toy를 입력하자 오류가 나는걸 확인할 수 있다.

fruitBox.add(new Fruit()); //ok
fruitBox.add(new Apple()); //ok
fruitBox.add(new Grape()); //ok
appleBox.add(new Apple()); //ok
appleBox.add(new Grape()); //에러