👩🏻‍💻 Programming/Java

Generic과 상속 (T extends)

한국의 메타몽 2022. 2. 4. 03:49

 

Generic 이란

 

간단하게 요약하면 클래스 내부에 지정하는 것이 아닌, 외부 사용자에 의해 지정되는 것을 의미한다.

예를 들어 Class 타입과 Interface 타입에 Generic을 지정하면 아래와 같다.

 

[ Class 타입 ]

class ClassGenericType<T> {
        private T t;
 
        public void set(T t) {
               this.t = t;
        }
        public T get() {
               return t;
        }
}

 

[ Interface 타입 ]

interface InterfaceGenericType<T1, T2> {
        T1 doSomething(T2 t);
        T2 doSomething2(T1 t);
}

이제 외부에서 해당 Class와 Interface 타입에 String을 넣느냐, Intenger를 넣느냐에 따라 타입이 결정된다.

Generic에 대한 디테일한 자료는 아래 링크를 참고하자.

 

[ 참고자료 : 탁구치는 개발자님의 Java Generic 정리 ]

 

Java Generic 정리

설계를 할때마다 Generic 사용법을 잊어먹는 경우가 많아 이해하기 쉬운 수준으로 정리를 해보려고 한다. Class generic type Class generic type은 다음과 같은 방법으로 클래스가 작성된다. 어떤 경우에 사

lng1982.tistory.com

 

 

Generic과 T Extends

 

Generic을 사용하면 클래스 외부에서 타입을 지정해주기 때문에 따로 타입을 체크하고 형변환을 해줄 필요가 없다.

또한 비슷한 기능을 지원하는 경우 코드의 재사용성이 높아진다는 장점이 있다.

 

하지만 생각해보자. 만약 Generic에 들어가서는 안될 타입이 들어가면 어떻게 될까?

아래의 상황을 가정해보자.

 

3D 프린터 클래스 'GenericPrinter'를 만든다.
이때 3D 프린터의 재료로 들어가는 Material 객체의 타입은 '파우더' 타입과 '플라스틱' 타입이 있다.
만약 '물' 타입이 3D 프린터의 타입으로 지정이 되면 안된다.

 

이런 경우, 간단하게 Generic을 상속시키면 된다.

즉, Meterial 타입을 Powder와 Plastic이 상속받도록 코드를 구현하면 된다.

그리고 GenericPrinter의 제네릭 T타입은 Mateiral을 상속받으면 된다.

 

 

 

[ Material ]

public abstract class Material {
    public abstract void doPrinting();
}

 

[ Plastic ]

public class Plastic extends Material{
    public String toString(){
        return " 재료는 Plastic 입니다.";
    }

    @Override
    public void doPrinting() {
    }
}

 

[ Powder ]

public class Powder extends Material{
    public String toString(){
        return "재료는 Powder 입니다.";
    }

    @Override
    public void doPrinting() {
    }
}

 

[ GenericPrinter ]

public class GenericPrinter<T extends Material>{
    private T material;

    public T getMaterial() {
        return material;
    }

    public void setMaterial(T material) {
        this.material = material;
    }

    public String toString(){
        return material.toString();
    }
}

 

[ GenericPrinterTest ]

public class GenericPrinterTest {
    public static void main(String[] args) {
        Powder powder = new Powder();
        GenericPrinter<Powder> powderPrinter = new GenericPrinter<>();
        powderPrinter.setMaterial(powder);

        Powder p = powderPrinter.getMaterial();
        System.out.println(powderPrinter.toString());

        Plastic plastic = new Plastic();
        GenericPrinter<Plastic> plasticPrinter = new GenericPrinter<>();
        plasticPrinter.setMaterial(plastic);

        Plastic p2 = plasticPrinter.getMaterial();
        System.out.println(plasticPrinter.toString());

        // GenericPrinter <Water> printer = new GenericPrinter<Water>(); // 상속받지 않은 Material이므로 선언 불가능
    }
}

 

[ GenericPrinterTest 결과 ]

재료는 Powder 입니다.
재료는 Plastic 입니다.