Java Generic - 제네릭 활용 문제
게임에서의 제네릭을 이용해보자.
먼저 예제로 사용할 아래의 보기 코드로 미리 만들고 진행한다.
BioUnit 부모 클래스를 생성하고 Marine, Zealot, Zergling 유닛들이 상속한다.
BioUnit 클래스는 이름과 체력의 멤버 필드가 있으며 Getter로 각각 호출할 수 있도록 한다. 생성자 또한 있어야하며 이름과 체력을 지정해 인스턴스로 생성이 가능하도록 한다.
BioUnit.class
public class BioUnit {
private String name;
private int health;
public BioUnit(String name, int health) {
this.name = name;
this.health = health;
}
public String getName() {
return name;
}
public int getHealth() {
return health;
}
@Override
public String toString() {
return "BioUnit{" +
"name='" + name + '\'' +
", health=" + health +
'}';
}
}
Marine.class
public class Marine extends BioUnit{
public Marine(String name, int health){
super(name, health);
}
}
Zealot.class
public class Zealot extends BioUnit {
public Zealot(String name, int health) {
super(name, health);
}
}
Zergling.class
public class Zergling extends BioUnit {
public Zergling(String name, int health) {
super(name, health);
}
}
UnitUtil 클래스 생성 - 제네릭 메소드와 상한 추가하기
아래와 실행 결과를 참고해 UnitUtil 클래스를 정의한다.
- UnitUtil.maxHealth() 메소드는 다음과 같다.
- 두 유닛의 입력을 받아 체력이 높은 유닛을 반환. 체력이 같은 경우 아무나 반환한다.
- 제네릭 메소드로 구현
- 두 인자에 입력되는 유닛의 타입은 모두 같아야한다.
Main.class 그리고 실행결과
public class Main {
public static void main(String[] args) {
Marine m1 = new Marine("마린1", 40);
Marine m2 = new Marine("마린2", 30);
Marine retMarine = UnitUtil.maxHealth(m1, m2);
System.out.println("남은 체력이 높은 마린 = " + retMarine);
Zealot z1 = new Zealot("질럿1", 100);
Zealot z2 = new Zealot("질럿2", 80);
Zealot retZealot = UnitUtil.maxHealth(z1, z2);
System.out.println("남은 체력이 높은 질럿 = " + retZealot);
}
}
남은 체력이 높은 마린 = BioUnit{name='마린1', health=40}
남은 체력이 높은 질럿 = BioUnit{name='질럿1', health=100}
풀이 UnitUtil 클래스 생성하기
UnitUtil.class
public class UnitUtil {
public static <T extends BioUnit> T maxHealth(T u1, T u2) {
return u1.getHealth() > u2.getHealth() ? u1 : u2;
}
}
Shuttle 클래스 생성 - 제네릭 메소드와 상한 추가하기
- 실행결과를 참고하여 Shuttle 클래스를 생성한다.
- 제네릭 타입으로 사용
- showInfo() 메소드를 통해 탑승 유닛 정보를 모두 출력
Main.class - 실행 결과
public class Main {
public static void main(String[] args) {
Shuttle<Marine> shuttle1 = new Shuttle<>();
shuttle1.in(new Marine("Marine1", 45));
shuttle1.showInfo();
Shuttle<Zealot> shuttle2 = new Shuttle<>();
shuttle2.in(new Zealot("Zealot1", 100));
shuttle2.showInfo();
Shuttle<Zergling> shuttle3 = new Shuttle<>();
shuttle3.in(new Zergling("Zergling1", 40));
shuttle3.showInfo();
}
}
BioUnit{name='Marine1', health=45}
BioUnit{name='Zealot1', health=100}
BioUnit{name='Zergling1', health=40}
풀이 - Shuttle.class
public class Shuttle<T extends BioUnit> {
private T unit;
public void in(T unit) {
this.unit = unit;
}
public void showInfo() {
System.out.println(unit);
}
}
다음 문제에 활용할 out 메소드도 추가한다.
Shuttle.class - 메소드 추가
public T out() {
return unit;
}
UnitPrinter - 제네릭 메소드와 와일드 카드 사용
앞에서 사용한 Shuttle 다시 활용한다.
- 실행 결과를 보고 UnitPrinter 클래스를 생성
- printT() 메소드는 제네릭 메소드로 정의한다.
- printW() 메소드는 와일드카드 파라미터로 정의한다.
- 이 두개는 셔틀 유닛 정보를 출력한다.
Main.class - 실행결과
public class Main {
public static void main(String[] args) {
Shuttle<Marine> shuttle1 = new Shuttle<>();
shuttle1.in(new Marine("Marine1", 45));
Shuttle<Zealot> shuttle2 = new Shuttle<>();
shuttle2.in(new Zealot("Zealot1", 100));
Shuttle<Zergling> shuttle3 = new Shuttle<>();
shuttle3.in(new Zergling("Zergling1", 40));
UnitPrinter.printT(shuttle1);
UnitPrinter.printW(shuttle2);
}
}
이름 = Marine1, 체력 = 45
이름 = Zealot1, 체력 = 100
풀이 - UserPrint.class
public class UnitPrinter {
public static <T extends BioUnit> void printT(Shuttle<T> t) {
T unit = t.out();
System.out.println("이름 = " + unit.getName() + ", 체력 = " + unit.getHealth());
}
public static void printW(Shuttle<? extends BioUnit> t) {
BioUnit unit = t.out();
System.out.println("이름 = " + unit.getName() + ", 체력 = " + unit.getHealth());
}
}