1. Generic Programing

변수의 선언이나 메서드의 매개 변수를 하나의 참조 자료형이 아닌
여러 자료형으로 변환 될 수 있도록 프로그래밍 하는 방식입니다.

실제 사용되는 참조 자료형으로의 변환은 컴파일러가 검증하므로 안정적입니다.

public class Plastic {}

public class Powder {}

모든 클래스는 'Object'의 하위 클래스이므로 자료형을 'Object'로 대체 할 수 있습니다.
그러므로 'Plastic'이든 'Powder'든 모든 재료의 타입으로 사용해 호출 할 수 있습니다.

public class TreeDPrinter {
	
	private Object material; 

	public Object getMaterial() {
		return material;
	}

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

모든 참조 자료형을 쓰고 싶다면 'Object'를 일단 쓸 수 있지만
원하는 타입으로 반환 받으려면 다운캐스팅이 필요합니다.

public class TreeDPrinterTest {

	public static void main(String[] args) {

		TreeDPrinter printer = new TreeDPrinter();
		
		printer.setMaterial(new Powder());
		
		Powder powder = (Powder)printer.getMaterial();
        // 다운캐스팅 하지 않는 경우 - Type mismatch: cannot convert from Object to Powder
		
	}
}

ㄱ) 제네릭 클래스 정의하기

여러 참조 자료형으로 대체 될 수 있는 부분을 하나의 문자로 표현합니다.
이 문자를 자료형 매개 변수 라고 합니다.
사용할 자료형이 대체 될 곳을 '<>' 표시로 감싸고 참조할 타입(클래스)을 쓰면 됩니다.

위에서 작성한 'TreeDPrinter' 클래스를 제네릭 클래스로 만들면 아래와 같습니다.

이후 제네릭 클래스 객체를 생성하고 메서드를 호출하는 것(TreeDPrinterTest)은
아래와 같이 변경 할 수 있습니다.
위에서는 다운캐스팅을 해야 했는데, 여기서는 제네릭 클래스로 참조할 타입을 명시하므로
따로 다운캐스팅(강제 형 변환) 할 필요 없이 컴파일 할 때에 자동으로 찾습니다.

public class TreeDPrinterTest {

	public static void main(String[] args) {

		TreeDPrinter<Powder> printer = new TreeDPrinter<Powder>();
		
		printer.setMaterial(new Powder());
		
		Powder powder = printer.getMaterial();
	}
}

.. 그나저나 ThreeDPrinter 라고 써야하는데 h를 빼먹었네요

a) 제네릭 클래스에서 대체 참조할 타입 제한하기

아래와 같이 대체할 참조 매개 변수에 'extends 제한할 클래스명(여기서는 Material)'을 추가하면 됩니다.
그러면 해당 클래스를 상속받은 타입만 사용할 수 있습니다.

public class TreeDPrinter<T extends Material> {}

이때 상위 클래스를 추상 클래스(abstract)로 설정하면서 메서드를 선언하면
구현 클래스에서 해당 메서드들을 구현하게 되는데
이 경우 'Object' 클래스의 메서드 뿐 아니라 새로 구현한 메서드 또한 호출 할 수 있습니다.

b) 자료형 매개 변수 T

'Type'의 의미로 'T'를 많이 사용합니다. <T>에서 <>는 다이아몬드 연산자 라고 합니다.
'static' 키워드를 사용하면 인스턴스 생성과 관계없이 메모리를 잡기 때문에 'T'에 사용할 수 없습니다.

다이아몬드 연산자 내부에서 자료형은 생략 가능 합니다.

ArrayList<String> list = new ArrayList<>();

자바 10부터 제네릭 자료형 추론이 가능합니다.

// 기존
ArrayList<String> list = new ArrayList<String>();

// 자바 10 이후
var list = new ArrayList<String>();
용어설명
GenericPrinter<Powder>제네릭 자료형(Generic Type), 매개 변수화 된 자료형(Parameterized Type)
Powder대입된 자료형

c) 제네릭에서 대입된 자료형을 명시하지 않는 경우

GenericPrinter<Powder> 과 같이 사용할 자료형(Powder)을 명시해야합니다.
자료형을 명시하지 않고 사용할 수는 있지만 이 경우 자료형을 명시하라는 경고가 나타납니다.
반환되는 형태에 따라 강제 형 변환을 해야 합니다.

이는 맨 처음 제네릭 프로그래밍을 이야기하면서 작성한 코드에서
다운캐스팅 한 것에 대한 이야기입니다.

ㄴ) 제네릭 메서드 활용하기

메서드의 매개 변수를 자료형 매개 변수로 사용하는 경우가 있습니다.

a) 자료형 매개 변수가 하나 이상인 경우

public class Point<T, V> {
    T x;
    V y;

    Point (T x, V y) {
    this.x = x;
    this.y = y;
    }

    public T getX() {
        return x;
    }

    public V getY() {
        return y;
    }
}
profile
백엔드 포지션 공부 중입니다.

0개의 댓글