본문 바로가기

개발/Java

상속에 있어서의 인스턴스 참조관계 일반화 정리

반응형

15 . 
상속에 있어서의 인스턴스 참조관계 일반화 정리 

class AAA {...}
class BBB extends AAA {...}
class BBB extends BBB {...}

이때 다음의 코드는 전혀 문제없이 컴파일 된다. 상위 클래스의 참조변수로도 하위 클래스의 인스턴스 참조가 얼마든지 가능하기 때문이다. 참고로 CCC클래스는 BBB의 하위 클래스이지만, AAA의 하위 클래스도 됨을 잊어서는 안된다. 

AAA ref1 = new BBB();
BBB ref2 = new CCC();
BBB ref3 = new CCC();

그렇다면 다음의 문장은 컴파일이 제대로 되겠는가?
CCC ref1 = . . . //  이 문장이 정상적으로 컴파일 되었다고 가정 
BBB ref2 = ref1;
AAA ref2 = ref1;

다음 사실에 근거하여 제대로 컴파일이 된다고 말할 수 잇다. 
"XXX 클래스의 참조변수는 XXX클래스의 인스턴스,
                                또는 XXX를 상속받는 하위 클래스의 인스턴스를 참조할 수있다. 

따라서 ref1이 참조하는 대상은 BBB와 AAA의 참조변수도 참조가 가능하다고 100%확신할 수 있다.
그렇다면 다음은?
AAA ref1 = new CCC();
BBB ref2 = ref1;            // 컴파일 에러 발생
CCC ref3 = ref1;           // 컴파일 에러 발생

처음 상속을 공부하는 여러분을 힘들게 하는 또다른 상황이 바로 이상황이다.
분명 ref1이 참조하는 대상은 BBB와 AAA의 하위 클래스인 CCC의 인스턴스이다. 따라서 ref2와 ref3를 이용한 참조에 전혀 문제가 없다고 생각할 수 있다.
그러나 컴파일러는 ref1이 참조하는 대상을AAA 클래스의 인스턴스라고 단순화시켜서 생각한다. 때문에 ref2와 ref3의 참조변수선언에서  컴파일 에러를 일으킨다.
따라서 만약에 위와같은 형태로 위와 같은 형태로 참조변수 ref2와 ref3을 선언해야 한다면, 다음과 같은 형 변환을 해야 한다. 

AAA ref1 = new CCC();
BBB ref2 = (CCC)ref1;          // 참조변수의 형 변환
CCC ref2 = (CCC)ref1;          // 참조변수의 형 변환

그러나 이렇게 형변화을 필요로 하는 경우은 드물며, 여러분의 프로그램 코드상에서 이러한 문장의 삽입이 필요하다면, 코드의 구성이 적절했는가에 대해서 반드시 고민해봐야 한다. 

++참고





RideAndLoad.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
28
29
30
31
32
33
34
35
36
37
38
39
40

class AAA {
    
    public void rideMethod() {System.out.println("AAA's Method");}
    public void loadMothod() {System.out.println("void Method");}
 
}
 
class BBB extends AAA {
    
    public void rideMethod() {System.out.println("BBB's Method");}
    public void loadMothod(int num) {System.out.println("int Method");}
    
}
 
 class CCC extends BBB {
     
    public void rideMethod() {System.out.println("CCC's Method");}
    public void loadMothod(double num) {System.out.println("double Method");}
    
 }
 
 class RideAndLoad {
     
     public static void main(String[] args)
     {
         AAA ref1 = new CCC();
         BBB ref2 = new CCC();
         CCC ref3 = new CCC();
 
         ref1.rideMethod();
         ref2.rideMethod();
         ref3.rideMethod();
         
         ref3.loadMothod();
         ref3.loadMothod(1);
         ref3.loadMothod(1.2);
     }
 }
 

 -- 실행결과 


위 예제를 통해 가장 먼저 발견해야 할 사실은 
"마지막으로 오버라이딩을 한 메소드만 호출된다."
"참조변수의 자료형에 상관없이 마지막으로 오버라이딩을 한 메소드만 호출된다."
즉 오버라이딩이 이뤄지만 오버라이디이 된 상위 클래스의 메소드는 어떠한 참조변수로도 호출이 불가능하도록 철저히 가려지는 것이다. 
오버라이딩을 한 하의 클래스의 메소드가 호출이 된다. 


 Friend.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
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
 
package infoManage;
 
public class Friend {
    String name;
    String phoneNum;
    String addr;
    
    public Friend (String nameString phone, String addr) {
        this.name=name;
        this.phoneNum = phone;
        this.addr = addr;
    }
    
    public void showData() {
        System.out.println("이름 : "+name);
        System.out.println("번호 : "+phoneNum);
        System.out.println("주소 : "+addr);
        
    }
    public void showBasicinfo() { }
 
}
 
class HighFriend extends Friend
{
 
    String job;
    
    
    public HighFriend(String nameString phone, String addr, String job) {
        super(name, phone, addr);
        this.job = job;
    }
    
    public void showData() {
        super.showData();
        System.out.println("직업 : "+ job);
    }
    public void showBasicInfo() {
        System.out.println("이름 : "+name);
        System.out.println("전화 : "+phoneNum);
    }
    
}
 
class UnivFriend extends Friend
{
    String major; // 전공 학과
 
    public UnivFriend(String nameString phone, String addr, String major) {
        super(name, phone, addr);
        this.major = major;
            
    }
    
    public void showData() {
        super.showData();
        System.out.println("전공 : "+major);
    }
    
    public void showBasicInfo() {
        System.out.println("이름 : "+name);
        System.out.println("전화 : "+phoneNum);
        System.out.println("전공 : "+major);
    
    }
    
}
 
cs


FriendsInfoHandler.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
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
 
package infoManage;
 
import java.util.Scanner;
 
public class FriendInfoHandler {
    
    private Friend[] myFriends;
    private int numOfFriends;
    
    public FriendInfoHandler(int num) {
        myFriends = new Friend[num];
        numOfFriends=0;
    }
    
    private void addFriendInfo(Friend fren) {
        myFriends[numOfFriends++= fren;
    }
    
    public void addFriend(int choice) {
        
        String name, phoneNum, addr, job, major;
        
        Scanner sc = new Scanner(System.in);
        System.out.println("이름 : "); 
        name = sc.nextLine();
        System.out.println("전화 : ");     
        phoneNum= sc.nextLine();
        System.out.println("주소 : "); 
        addr = sc.nextLine();
        
        if(choice ==1) {
            System.out.println("직업 : "); 
            job = sc.nextLine();
            addFriendInfo(new HighFriend(name, phoneNum, addr, job));
        }
        else 
        {
            System.out.println("학과 : ");
            major = sc.nextLine();
            addFriendInfo(new UnivFriend(name, phoneNum, addr, major));
        }
        
    }
    
    public void showAllData() {
        for (int i = 0; i <numOfFriends; i++) {
            
            myFriends[i].showData();
            System.out.println("");
        }
    }
    
    public void showAllSimpleData() {
        for (int i = 0; i <numOfFriends; i++) {
            myFriends[i].showBasicinfo();
            System.out.println("");
        }
    }
    
}
cs


MyFriendInfoBook.java  //Main

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
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
 package infoManage;
 
import java.util.Scanner;
 
public class MyFriendInfoBook {
    
    public static void main(String [] args) {
        FriendInfoHandler handler = new FriendInfoHandler(10);
        
        while(true)
        {
            System.out.println("*** 매뉴선택 ***");
            System.out.println("1. 고교 정보 저장");
            System.out.println("2. 대학 친구 저장");
            System.out.println("3. 전체 정보 출력");
            System.out.println("4. 기본 정보 출력");
            System.out.println("5. 프로그램 종료");
            System.out.println("선택 >> ");
            
            Scanner sc = new Scanner(System.in);
            int choice = sc.nextInt();
            
            switch(choice)
            {
            case 1 : case 2 :
                 handler.addFriend(choice);
                 break;
            case 3 :
                 handler.showAllData();
                 break;
            case 4 :
                handler.showAllSimpleData();
                break;
            case 5 : 
                System.out.println("프로그램을 종료합니다.");
                return;
                
            }
            
        }
    }
 
}
 
cs
FriendInfoHandler 클래스는 상속을 통해 연관된 HighFriend, UnivFriend 클래스에 대해
(일련의 클래스에 대해) 동일한 방식으로 배열에 저장 및 메소드 호출을 할 수 있습니다. 

반응형
LIST

'개발 > Java' 카테고리의 다른 글

객체지향프로그래밍의 이해와 자바의 이름규칙  (0) 2018.05.19
메모리 구조  (0) 2018.05.19
구조체란?  (0) 2018.05.19
17 abstract 클래스  (0) 2018.05.19
접근제어 지시자(Access Control Sperifiers)  (0) 2018.05.19