프로그래밍을 하다보면 여러 자료형이 쓰일 수 있는 변수가 존재할 경우 이 변수를 기반으로 클래스를 만들어야 할 것이다. 이런 경우 비슷한 코드를 자료형에 따라 여러개의 클래스를 만들게 된다면 overhead가 발생할 것이다.
우리는 이러한 상황이 발생하는 경우 여러 자료형을 담을 수 있는 Generic class을 사용하며 프로그래밍을 하여야한다.
Generic class은 자료형을 특정하지 않고 추후 해당 클래스를 사용할 때 지정 할 수 있도록 선언하는 방법을 사용한다.
이러한 Generic class을 사용하여 다양한 자료형이 적용될 수 있는 class나 method를 만드는 것을 generic programming이라고 한다.
Generic class은 자바 5.0부터 제공이 되었다.
Collection Framework에서 많이 사용되고 있다.
즉, 자료형을 특정하지 않아 사용을 할 때 원하는 자료형을 선언하여 사용하게 해주는 변수를 generic class이라고 하며 해당 변수를 사용하는 프로그래밍을 Generic Programming이라고 한다.
public class GenericPrinter<T>
private T material;
public T getMaterial() {
return material;
}
public void setMaterial(T material) {
this.material = material;
}
GenericPrinter<Powder> powderPrinter = new GenericPrinter<>();
Powder.java
package ch06;
public class Powder {
public String toString() {
return "재료는 powder입니다. ";
}
}
ThreeDPrinter1.java
package ch06;
public class ThreeDPrinter1 {
private Powder material;
public Powder getMaterial() {
return material;
}
public void setMaterial(Powder material) {
this.material = material;
}
public String toString() {
return "재료는 Powderrf 입니다.";
}
}
위의 Powder class와 비슷한 다른 객체를 생성하는 경우 TheeDPrinter코드도 해당 class가 생성됨에 따라 따로 만들어져야 할 것이다. 또는 아래 코드와 같이 Object를 사용하여 코딩할 수도 있다. 하지만 Object의 경우 인스턴스를 생성하고 사용을 할 때 형변환을 해줘야하는 번거로움이 발생한다.
ThreeDPrinter3.java
package ch06;
public class ThreeDPrinter3 {
private Object material;
public Object getMaterial() {
return material;
}
public void setMaterial(Object material) {
this.material = material;
}
public String toString() {
return "재료는 Powderrf 입니다.";
}
}
ThreeDPrinterTest.java
package ch06;
public class ThreeDPrinterTest {
public static void main(String[] args) {
// TODO Auto-generated method stub
Powder powder = new Powder();
ThreeDPrinter3 printer = new ThreeDPrinter3();
printer.setMaterial(powder);
Powder p = (Powder)printer.getMaterial();
// ThreeDPrinter3의 경우는 Object type을 이용하여 material을 만들었는데
// 이럴 경우 형 변환을 해줘야해서 번거로움이 발생한다.
// 그래서 generic programming이 생겨났다.
}
}
GenericPrinter.java
package ch06;
public class GenericPrinter<T> {
// T는 자료형 매개변수로 이 클래스를 사용하는 시점에 실제 사용할 자료형을 지정하며 static 변수는 사용할 수 없다
private T material;
// 나중에 사용할 때 사용할 자료형을 입력하면 해당 자료형으로 생성된다.
public T getMaterial() {
return material;
}
public void setMaterial(T material) {
this.material = material;
}
public String toString() {
return material.toString();
}
}
GenericPrinterTest.java
package ch06;
public class ThreeDPrinterTest {
public static void main(String[] args) {
// TODO Auto-generated method stub
Powder powder = new Powder();
ThreeDPrinter3 printer = new ThreeDPrinter3();
printer.setMaterial(powder);
Powder p = (Powder)printer.getMaterial();
// ThreeDPrinter3의 경우는 Object type을 이용하여 material을 만들었는데
// 이럴 경우 형 변환을 해줘야해서 번거로움이 발생한다.
// 그래서 generic programming이 생겨났다.
}
}
※ 그 외 코드는 위와 중복되어 생략
<T extends 클래스>를 사용하면 T 자료형의 범위를 제한할 수 있다.
Generic class에 상위 클래스 상속을 할 경우 T에는 상속을 받은 Class(자료형)으로만 생성 가능하다.
상속을 받지 않는 경우 T는 Object로 변환되어 Object 클래스가 기본으로 제공하는 메서드만 사용가능하다.
extends를 사용함으로써 사용할 수 있는 class에 대하여 제한을 걸어두고 공통으로 사용하는 method들을 지정해줄 수 도 있다.
Material.java
package ch07;
//Generic class의 제한을 걸기 위한 class로
//해당 class는 직접 쓸 일이 없기에 abstract로 생성하였다.
public abstract class Material {
public abstract void doPrinting();
}
Plastic
package ch07;
public class Plastic extends Material {
public String toString() {
return "재료는 plastic 입니다. ";
}
@Override
public void doPrinting() {
// TODO Auto-generated method stub
}
}
GenericPrinter
package ch07;
public class GenericPrinter<T extends Material> {
// extends Material을 하여 T에 대한 제한을 하였다.
// Material을 상속받은 Class(자료형)으로만 생성 가능하다!!
private T material;
// 나중에 사용할 때 사용할 자료형을 입력하면 해당 자료형으로 생성된다.
public T getMaterial() {
return material;
}
public void setMaterial(T material) {
this.material = material;
}
public String toString() {
return material.toString();
}
}
※ 그 외 코드는 위와 중복되어 생략