상속 관계의 클래스 객체 형변환

  • 부모 : Account 클래스
    • 필드 : accountNo, ownerName, balance
    • 메소드 : deposit(), cardNo()
  • 자식 : CheckingAccount 클래스
    • 필드 : cardNo
    • 메소드 : pay()

조건

obj1 은 Account의 타입 객체로 생성한다.
obj2 은 CheckingAccount 타입 객체로 생성한다.
obj 는 Account 타입 객체이지만 CheckingAccount 타입으로 형변환한다.
잘못된 형변환 예제를 고쳐서 캐스팅 형변환이 가능하도록 한다.

  • 스택영역 : obj, obj1, obj2 (참조형 변수들)
  • 힙 영역 : obj, obj1, obj2 참조형 변수들 클래스 타입의 객체 주소

출력 결과

지불이 불가능합니다.

예제 코드

  • Account.java 부모 클래스
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    
      public class Account {
      String accountNo;  //계좌번호
      String ownerName; //예금주 이름
      int balance;   //잔액
        
      //Account() {  
      //}
        
      Account(String accountNo, String ownerName, int balance) { 
      this.accountNo = accountNo; 
      this.ownerName = ownerName; 
      this.balance = balance; 
      } 
        
      void deposit(int amount) { 
      balance += amount;
      }
        
      int withdraw(int amount) throws Exception {
      if (balance < amount) 
          throw new Exception("잔액이 부족합니다."); 
      balance -= amount;
      return amount;
      }
      }
    
  • CheckingAccount.java 자식 클래스
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    
      public class CheckingAccount extends Account {
          String cardNo; 	//직불카드 번호 필드
            
          //CheckingAccount() {	//super() : 부모 클래스 디폴트 생성자 자동 호출
          //	super();	//this();
          //}
            
          CheckingAccount(String accountNo, String ownerName,
              int balance, String cardNo) { // 생성자
              //super();
              super(accountNo, ownerName, balance);	//명시적으로 부모 클래스 생성자 호출
                
              //this.accountNo = accountNo;
              //this.ownerName = ownerName;
              //this.balance = balance;
              this.cardNo = cardNo;
          }
            
    
          int pay(String cardNo, int amount) throws Exception 
          { 
          if (!cardNo.equals(this.cardNo) || (balance < amount))
                  throw new Exception("지불이 불가능합니다.");
              return withdraw(amount);
          }
    
      }
    
  • RefTypeExample6.java 잘못된 캐스팅 형변환 실행코드
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    
      public class RefTypeExample6 {
          public static void main(String args[]) {
          Account obj = new CheckingAccount("111-22-33333333",
          "홍길동", 10, "4444-5555-6666-7777");
          CheckingAccount obj2 = obj;
              try {
                  int amount = obj2.pay("4444-5555-6666-7777", 47000); 
                  System.out.println("인출액: " + amount);
                  System.out.println("카드번호: " + obj2.cardNo);
              }
              catch (Exception e) { 
                  System.out.println(e.getMessage());
              }
          }
      }
    

    부모에게 없는 필드에 접근을 요청하기 때문에 자식객체는 부모클래스에 있는 필드와 메소드에 접근할 수 없다.

작성 코드

  • RefTypeExample6.java 캐스팅 형변환을 실행한 실행 코드
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    
      public class RefTypeExample6 {
          public static void main(String args[]) {
                
              Account obj1 = new Account("AAA", "AA", 10);
                
              Account obj = new CheckingAccount("111-22-33333333", "홍길동", 10, "4444-5555-6666-7777");
    
              CheckingAccount obj2 = (CheckingAccount)obj; //강제 형변환, 대입이 가능해진다.
                
                
              try {
                  int amount = obj2.pay("4444-5555-6666-7777", 47000); 
                  System.out.println("인출액: " + amount);
                  System.out.println("카드번호: " + obj2.cardNo);
              }
              catch (Exception e) { 
                  System.out.println(e.getMessage());
              }
          }
      }
    

    • obj 객체가 주소 100번지의 CheckingAccount 클래스를 가리키는 Account 클래스 타입 객체이다.
      (ojb 객체 주소 : 100번지)
    • 그러면 CheckingAccount클래스에서 Account에 생성된 필드와 메소드만(상속된 것만) 접근이 가능하다.
    • 캐스팅 형변환으로 CheckingAccount 클래스 타입인 obj2 객체가 obj의 100번지 주소를 가르키고 있다고 알려주기 때문에 접근이 가능하다.
      (ojb2 객체 주소 : 100번지)

문법적인 오류는 없지만 실행오류가 나는 실행코드

  • RefTypeExample6.java 문법적인 오류는 없지만 try 실행시 obj2.pay를 수행하지 못한다
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    
      public class RefTypeExample6 {
          public static void main(String args[]) {
            
          Account obj1 = new Account("AAA", "AA", 10); //CheckingAccount 형변환 타입이 아니다
          CheckingAccount obj2 = (CheckingAccount)obj1;  //오류
          Account obj = new CheckingAccount("111-22-33333333", "홍길동", 10, "4444-5555-6666-7777");
          //  CheckingAccount obj2 = (CheckingAccount)obj; //강제 형변환, 대입이 가능해진다.
              try {
                  int amount = obj2.pay("4444-5555-6666-7777", 47000); 
                  System.out.println("인출액: " + amount);
                  System.out.println("카드번호: " + obj2.cardNo);
              }
              catch (Exception e) { 
                  System.out.println(e.getMessage());
              }
          }
      }
    

    • Account 타입의 obj1 객체가 200번지의 Account 클래스를 가리키고 있다.
      (obj1 객체주소 : 200번지)
    • CheckingAccount 타입의 obj2 객체도 똑같이 200번지의 Account 클래스를 가리키게 된다.
      (obj2 객체주소 : 200번지)


오류 원인

CheckingAccount obj2 = (CheckingAccount) obj1;

  • 문법적인 형식은 잘못이 없지만 obj1 이 가리키고 있는 객체 앞에 있는 형변환의 타입(new Account(“AAA”, “AA”, 10);)이 아니면 오류가 난다.
  • Account 타입의 obj1 객체를 변환한다고 CheckingAccount 타입으로 바뀌진 않는다.
    Account 타입의 obj1이 Account(new Account(“AAA”, “AA”, 10);) 객체정보만 가지고 있어서
    CheckingAccount에 있는 정보를 접근할 수 없기 때문에 형변환이 안 된다.
  • obj2는 CheckingAccount의 필드와 메소드 정보를 가지고 있으나
    obj1이 가리키는 Account 클래스에는 CheckingAccount클래스의 필드와 메소드(ex : cardNo())가 없기 때문에
    허용이 되지 않아 사용하지 못 한다.

🌞 정보 : 공부 기록용 블로그입니다. 오타나 내용 오류가 있을 경우 알려주시면 감사하겠습니다.

태그:

카테고리:

업데이트:

댓글남기기