인터페이스 타입캐스팅과 다형성 활용

서버란·2024년 8월 31일

자바 궁금증

목록 보기
6/35

Unit 클래스

public abstract class Unit {

    protected String name;
    protected int hp;
    protected int attackPower;

    public Unit(String name, int hp, int attackPower) {
        this.name = name;
        this.hp = hp;
        this.attackPower = attackPower;
    }

    public void setHp(int hp) {
        this.hp = hp;
    }

    public String getName() {
        return this.name;
    }

    public int getHp() {
        return this.hp;
    }

    public int getAttackPower() {
        return this.attackPower;
    }

}

Marine 클래스


public class Marine extends Unit implements Attackable{
    public Marine(String name, int hp, int attackPower) {
        super(name, hp, attackPower);
    }

    public void attack(Unit unit) {
        System.out.println(this.name + "이 " + unit.getName() + "을 원거리 공격합니다.");
        unit.setHp(unit.getHp() - this.attackPower);
    }
}

Medic 클래스

public class Medic extends Unit {
    public Medic(String name, int hp, int attackPower){
        super(name, hp, attackPower);
    }
}

형변환 해야되는 이유

List<Unit> list = new .....
for(Unit unit : list)
	((Attackable) unit).attack(unit); // ?
  • attackable 이유
    ((Attackable) unit).attack(unit);에서 (Attackable)로 형 변환을 하는 이유는, Unit 클래스가 Attackable 인터페이스를 구현하고 있는지 여부에 따라 attack 메서드를 호출할 수 있는지 확인하기 위함입니다.

  • 이를 좀 더 자세히 설명하자면:

  1. 인터페이스와 다형성:
    • Unit 클래스는 Attackable 인터페이스를 구현하지 않습니다.
      반면, Marine 클래스는 Attackable을 구현하고 있습니다.
    • Attackable 인터페이스는 attack 메서드를 정의하고 있으며, 이를 구현하는 클래스는 실제로 attack 메서드를 제공해야 합니다.
  2. 형 변환 필요성:
    • List은 Unit 타입의 객체들을 저장하는 리스트입니다. 하지만 Unit 클래스는 Attackable을 구현하지 않으므로, List의 객체들을 직접 Attackable 타입으로 다룰 수 없습니다.
    • 따라서 unit이 Attackable을 구현하는 객체인지 확인하고, 맞다면 attack 메서드를 호출할 수 있도록 형 변환을 해야 합니다.
  3. 형 변환 코드:
    List<Unit> list = new....
    for(Unit unit : list)
    	if (unit instanceof Attackable)
    			((Attackable) unit).attack(unit); // O
    • if (unit instanceof Attackable)은 unit이 Attackable 인터페이스를 구현하는 객체인지 확인합니다.
    • ((Attackable) unit).attack(unit);는 unit이 실제로 Attackable을 구현하고 있는 경우에만 attack 메서드를 호출합니다.
  4. 왜 unit을 attack 메서드에 전달하는가?:
    • attack 메서드는 대상 Unit을 공격하기 위한 메서드입니다. 따라서 현재 객체(unit)가 다른 unit을 공격하는 방식으로 메서드를 호출합니다.
    • 전체적으로, ((Attackable) unit).attack(unit);에서 형 변환을 사용하는 이유는 Unit 타입의 객체가 Attackable 타입으로 다뤄질 때만 attack 메서드를 호출할 수 있기 때문입니다. 이 접근 방식은 자바의 다형성과 타입 체크를 활용하여 코드의 안전성을 높이는 방법 중 하나입니다.
  1. 예제 코드 설명
for (Unit unit : list) {
    if (unit instanceof Attackable) {
        ((Attackable) unit).attack(unit);
    }
}
  • unit instanceof Attackable 조건문을 통해 현재 unit이 Attackable을 구현하는 객체인지를 체크합니다.
  • ((Attackable) unit).attack(unit);에서 형 변환을 통해 unit을 Attackable 타입으로 변환한 후, attack 메서드를 호출합니다.
    이렇게 하는 이유는 unit이 Attackable 인터페이스를 구현하는 객체일 때만 attack 메서드가 정의되어 있기 때문입니다. 따라서 unit이 Attackable일 때만 attack 메서드를 안전하게 호출할 수 있습니다.

결론

  • 타입의 일관성: 자바는 타입에 따라 메서드를 호출하도록 설계되어 있습니다.
    따라서 Unit 객체는 Attackable 타입으로 다뤄질 때만 attack 메서드를 호출할 수 있습니다.
  • 형 변환: Unit 객체를 Attackable 타입으로 변환함으로써, Attackable 인터페이스에서 정의한 메서드를 사용할 수 있습니다.
    이러한 방식은 자바의 타입 시스템과 다형성의 원리를 활용하여 코드의 안전성을 높이고, 런타임에서 메서드를 호출하기 전에 타입을 확인하는 좋은 방법입니다.
profile
백엔드에서 서버엔지니어가 된 사람

0개의 댓글