Raw Type의 슈퍼 클래스는 Raw Type이다. 상속 받지 않은 Raw Type의 생성자, 인스턴스 메서드, 인스턴스 필드는 Raw Type이다.
class Shape { } //Raw Type
class FruitBox<T> extends Shape { } //Generic Type
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 toString() { return list.toString(); }
}
class FruitBox<T> extends Box<T> { } // 이와 같이 generic class를 상속 받을 수 있다.
class Box<T> { ... }
class FruitBox<T extends Fruit> extends Box<T> { }
위와 같이 기능은 Box에 있는 곳을 상속 받되, 내부에 들이는 객체의 자료형은 Fruit로 제한할 수 있다.
class Box<T extends Fruit> { ... }
class FruitBox<T> extends Box<T> { ... } // Error
위와 같이 Box 클래스는 Fruit로 제한을 걸어 두었으나 FruitBox는 Box를 상속받으면서도 Fruit를 제한하지 않았다.
class Box<T extends Fruit> { ... }
class FruitBox<T extends Fruit> extends Box<T> { ... } // OK
class Juicer {
static Juice makeJuice(FruitBox<Fruit> box) {
String tmp = "";
for(Fruit f : box.getList()) tmp += f + " ";
return new Juice(tmp);
}
}
위와 같이 생긴 클래스가 있다고 가정하자. 여기에서 box.getList()는 ArrayList로 작성된 FruitBox 에서 리스트를 반환하는 함수이다.
더 자세한 클래스와 코드에 대한 설명은 이후에서 다루도록 하겠다.
FruitBox<Fruit> fruitBox = new FruitBox<Fruit>();
FruitBox<Apple> appleBox = new FruitBox<Apple>();
fruitBox = new FruitBox<Fruit>();
appleBox = new FruitBox<Apple>();
System.out.println(Juicer.makeJuice(fruitBox)); // OK
System.out.println(Juicer.makeJuice(appleBox)); // Error: the argument is not of type FruitBox<Fruit>.
이제 중요한 것은 위와 같이 작성하였을 때 appleBox를 집어넣은 곳에서 에러가 난다. 왜냐하면 Juicer에서 파라미터로 FruitBox<Furit>
을 받기로 하였기 때문이다.
그래서 코드를 다음과 같이 바꾸면 어떻게 될까?