코드 그라데이션

<보충> upCasting과 downCasting 본문

Java/Mega

<보충> upCasting과 downCasting

완벽한 장면 2023. 5. 3. 22:07

업캐스팅과 다운캐스팅

예시

public class Main {

  public static void main(String[] args) {
    Scanner sc = new Scanner(System.in);
    double num = sc.nextInt();
  }

}

이거 에러 나지 않는다. => 큰 그릇에 작은 애를 담았으므로

upCasting => 암묵적 캐스팅

 

하지만

public class Main {

  public static void main(String[] args) {
    Scanner sc = new Scanner(System.in);
    double numA = sc.nextInt();
    int numB = numA; // 에러
  }

}

이건 에러.

=> 우리(개발자)는 double타입으로 선언했으나, 이것이 int가 들어갈 것을 알고 있지만,

   컴파일러 입장에서는 작은 타입(int)에 큰 타입(double)의 수를 넣는다고 오해하고, 에러를 내게 된다.

 

따라서 이렇게 바꿔줘서 에러를 해결해야 한다.

명시적 캐스팅(downcasting)

public class Main {

  public static void main(String[] args) {
    Scanner sc = new Scanner(System.in);
    double numA = sc.nextInt();
    int numB = (int)numA;
  }

}

 


클래스 예시

class Parent {

}

class Child extends Parent {

}

public class Main {

  public static void main(String[] args) {
    Parent parent = new Child(); //가능, 업캐스킹
    // 상위 타입에 하위 타입을 담으면, 얼마든지 담을 수 있다.

    //Child child = new Parent(); //불가능
    //Child child = parent; // 이것도 불가능.
    // 위에서 Child를 담았지만, 타입 자체가 Parent이기 때문에
    // 컴파일러는 여기서 검사할 때 타입만 검사한다. 에러

    // 따라서 명시적 캐스팅(down casting) 필요
    Child child = (Child) parent;
    
  }
}

 

여기서 헷갈리지 말아야 할 것은 일반적으로 부모 클래스보다 상속받은 자식 클래스의 개념이 더 크다는 것.

 

그냥 분리(기본자료형과 클래스를) 해서 생각하는게 더 속 편할 것.

 

클래스의 경우,

Parent라는 껍데기에 자식이 들어오면,

자식은 부모+a 이므로 에러 나지 않는다.

 

그런데,

Child(자식) 껍데기에 부모(Parent)가 들어오면,

부모는 자식이 하는 일을 다 하지 못하니까 위험하다.

 

ex.

최신형 세탁기에 낡은 엔진이 들어가면, 낡은 엔진은 추가된 세탁기 기능을 다 따라가지 못한다.

하지만 낡은 껍데기에 최신형 엔진이 들어가면, 최신형은 옛날 기능도 가지고 있기 때문에 충분히 기능 소화가 가능하다.

예시 그림

 

class Parent {

}

class Child extends Parent {

}

public class Main {

  public static void main(String[] args) {
    Parent parent = new Parent();

    Child child = (Child) parent; // 이것도 가능은 함.

  }
}

타입은 Parent지만 개발자가 "child가 들어왔다고 내가 보증할게" 가 된다. 

 

컴파일러는 판단할 때 타입만 보기 때문에 

 Parent parent = new Parent();
// Parent parent1 = new Child();

이거 두개가 사실상 같다고 판단함.

하지만 실행하면

Exception in thread "main" java.lang.ClassCastException: 
	class mega.backend_onemore.Day24.Parent cannot be cast to class 
    	mega.backend_onemore.Day24.Child (mega.backend_onemore.Day24.Parent and mega.backend_onemore.Day24.Child are in unnamed module of loader 'app')
at mega.backend_onemore.Day24.Main.main(Main.java:17)

이런 컴파일 에러가 난다.

 


instanceof

- 때로는 타입이 아니라 진짜 객체가 뭔지 궁금할 때가 있음.

class Parent {

}

class Child extends Parent {

}

public class Main {

  public static void main(String[] args) {
    Parent parent = new Parent();
    if (parent instanceof Parent) {
      System.out.println("True");
    }
    else {
      System.out.println("False");
    }

  }
}

실행 결과

True

 

class Parent {

}

class Child extends Parent {

}

public class Main {

  public static void main(String[] args) {
    Parent parent = new Child();
    if (parent instanceof Parent) {
      System.out.println("True");
    }
    else {
      System.out.println("False");
    }

  }
}

실행 결과

True

 

또다른 예시 1

class Parent {

}

class Child1 extends Parent {

}
class Child2 extends Parent {

}

public class Main {

  public static void main(String[] args) {
    Parent parent1 = new Child1();
    Parent parent2 = new Child2();

    if (parent1 instanceof Child1) {
      System.out.println("True");
    } else {
      System.out.println("False");
    }
    System.out.println("================");

    if (parent2 instanceof Child2) {
      System.out.println("True");
    } else {
      System.out.println("False");
    }
    
  }
}

실행 결과

True
================
True

 

또다른 예시 2

class Parent {

}

class Child1 extends Parent {

}
class Child2 extends Parent {

}

public class Main {

  public static void main(String[] args) {
    Parent parent1 = new Child1();
    Parent parent2 = new Child2();

    if (parent1 instanceof Child2) {
      System.out.println("True");
    } else {
      System.out.println("False");
    }
    System.out.println("================");

    if (parent2 instanceof Child2) {
      System.out.println("True");
    } else {
      System.out.println("False");
    }

  }
}

실행 결과

False
================
True

 

자식은 부모 객체라고도 볼 수 있다.


또다른 예시 3

이게 가장 헷갈리는 부분

class Parent {

}

class Child extends Parent {

}


public class Main {

  public static void main(String[] args) {
    Parent parent = new Parent();

    if (parent instanceof Child) {
      System.out.println("True");
    } else {
      System.out.println("False");
    }
  }
}

실행 결과

false

=> 여기서 물어보는 것은 parent가 Child의 인스턴스로서 역할을 할 수 있느냐.

더 쉽게 말하자면 parent가 Child일 수 있느냐.

그런데 Child는 확장된 거고, parent는 확장 안 된 거니까, 이건 false

728x90
Comments