본문 바로가기

IT/Java

10_상속(Inheritance) : 클래스 상속, 메소드 재정의(@Override)

01. 상속(inheritance)이란?

- 객체 지향 프로그램에서 부모 클래스(상위 클래스)의 멤버를 자식 클래스(하위 클래스)에게 물려주는 것.

- 부모 클래스에서 private 접근 제한을 갖는 필드와 메소드는 상속 대상에서 제외된다.

- 부모 클래스와 자식 클래스가 다른 패키지에 존재한다면 default 접근 제한을 갖는 필드와 메소드도 상속 대상에서 제외된다.

- final 클래스는 상속할 수 없으며 final 메소드는 오버라이딩할 수 없다.

 

02. 클래스 상속

- 상속 관계를 나타내기 위해 extends 키워드를 사용한다.

1
2
3
4
5
class 자식클래스 extends 부모클래스 {
    //필드
    //생성자
    //메소드
}
 

 

예제) 

- 핸드폰(Cellphone) 클래스를 상속해서 스마트폰(SmartPhone)클래스를 작성한다.

- 핸드폰이 부모 클래스가 되고, 스마트폰이 자식 클래스가 된다.

 

휴대폰의 모델과 컬러는 제각기 다르므로 필드를 초기화하지 않았다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class CellPhone {
    //필드
    String model;
    String color;
    
    //생성자
    
    //메소드
    void powerOn() { System.out.println("전원을 켭니다"); }
    void powerOff() { System.out.println("전원을 끕니다"); }
    void ring() { System.out.println("벨이 울립니다");}
    void sendVoice(String message) { System.out.println("나 : " + message); }
    void receiveVoice(String message) { System.out.println("상대방 : " + message); }
    void hangUp() { System.out.println("전화를 끊습니다"); }
    
}
 
http://colorscripter.com/info#e" target="_blank" style="color:#e5e5e5text-decoration:none">Colored by Color Scripter
 
 
 
스마트폰의 생성자 매개값에 부모인 핸드폰 클래스의 필드인 model과 color를 넣어준다.
스마트폰 객체를 생성할 때 마다 모델과 컬러를 지정해주기 위해서이다.
 
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
public class SmartPhone extends CellPhone {
    //필드
    int channel;
    
    //생성자
    SmartPhone(String model, String color, int channel){
        this.model = model;
        this.color = color;
        this.channel = channel;
    }
    
    //메소드
    void turnOnTv() {
        System.out.println(channel + "번 채널 방송 수신을 시작합니다");
    }
    
    void changeChannelTv(int channel) {
        System.out.println(channel + "번 채널로 바꿉니다");
    }
    
    void turnOffTv() {
        System.out.println("TV 수신을 종료합니다");
    }
 
}
 
http://colorscripter.com/info#e" target="_blank" style="color:#e5e5e5text-decoration:none">Colored by Color Scripter
 

 

실행클래스에서 Smartphone 객체를 생성하였다. 겉으로 보기에는 스마트폰 객체만 만들어진 것 같지만 사실 내부적으로 부모객체인 Cellphone의 객체가 먼저 생성된 후 자식 객체가 생성된다.

 

스마트폰 객체를 통해서 cellphone으로부터 상속받은 필드와 메소드를 그대로 사용할 수 있다.

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
public class SmartPhoneExample {
    public static void main(String[] args) {
        //SmartPhone 객체 생성 - 사실 내부적으로 부모객체인 CellPhone의 객체가 먼저 생성된 후 자식 객체가 생성된다.
        SmartPhone sphone = new SmartPhone("자바폰""검정"10);
        
        //cellphone으로부터 상속 받은 필드
        System.out.println("모델 : " + sphone.model);
        System.out.println("색상 : " + sphone.color);
        
        //SmartPhone의 필드
        System.out.println("채널 : " + sphone.channel);
        
        //cellphone으로 부터 상속 받은 메소드 호출
        sphone.powerOn();
        sphone.ring();
        sphone.sendVoice("Allo!");
        sphone.receiveVoice("Bonjour, c'est Celine.");
        sphone.sendVoice("TG");
        sphone.hangUp();
        
        //SmartPhone의 메소드 호출
        sphone.turnOnTv();
        sphone.changeChannelTv(12);
        sphone.turnOffTv();
        
    }
}
 
http://colorscripter.com/info#e" target="_blank" style="color:#e5e5e5text-decoration:none">Colored by Color Scripter
 

 

 

03. 메소드 재정의(@Override)

- 상속 받은 메소드 중 어떤 것은 자식 클래스가 사용하기에 적합하지 않을 수 있다. 이러한 경우 상속된 일부 메소드를 자식 클래스에서 수정해서 사용하기 위해 메소드 오버라이딩(Overriding) 기능을 사용한다.

- 자식 객체에서 메소드를 호출하면 오버라이딩된 자식 메소드가 호출 된다.

- 부모의 메소드를 호출하고 싶으면 super.부모메소드(); 의 형태로 코드를 작성한다.

- @Override 어노테이션은 생략할 수 있으나, 이것을 붙여주면 정확히 오버라이딩 되었는지 컴파일러가 체크해주므로 실수를 줄일 수 있다.

 

*메소드 오버라이딩의 조건

1. 부모의 메소드와 동일한 리턴타입, 메소드 이름, 매개변수 리스트를 가져야 한다.

2. 오버라이딩 할 때 접근제한을 강화할 수 없다.

3. 새로운 예외를 던질(throw) 수 없다.

 

예제)

- 부모클래스 : 이어폰(Earphones)

- 자식클래스 : 노이즈캔슬링 이어폰(NoiseCancellingEarphones)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
package ex02_method;
 
public class Earphones {
        public void connect() {
            System.out.println("이어폰을 연결합니다");
        }
        
        public void play() {
            System.out.println("일반모드로 재생합니다");
        }
 
        public void disconnect() {
            System.out.println("이어폰 연결을 해제합니다");
        }
    }
 
http://colorscripter.com/info#e" target="_blank" style="color:#e5e5e5text-decoration:none">Colored by Color Scripter
 

 

- 노이즈캔슬링 모드로 설정되었으면 오버라이드한 play(); 메소드를 실행하고

- 일반모드로 설정되었으면 부모클래스인 play(); 메소드를 호출함

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class NoiseCancellingEarphones extends Earphones {
    public static final int NORMAL = 1;
    public static final int NOISECANCELLING = 2;
 
    public int playMode = NORMAL;
 
    @Override
    public void play() {
        if (playMode == NOISECANCELLING) {
            System.out.println("노이즈캔슬링 모드로 재생합니다");
        } else {
            // Earphone객체의 play() 메소드 호출
            super.play();
        }
    }
}
 
http://colorscripter.com/info#e" target="_blank" style="color:#e5e5e5text-decoration:none">Colored by Color Scripter
 
1
2
3
4
5
6
7
8
9
10
11
12
13
public class NoiseCancellingEarphonesExample {
    public static void main(String[] args) {
        NoiseCancellingEarphones ncEarphones = new NoiseCancellingEarphones();
        ncEarphones.connect();
        ncEarphones.playMode = NoiseCancellingEarphones.NOISECANCELLING;
        ncEarphones.play();
        ncEarphones.playMode = NoiseCancellingEarphones.NORMAL;
        ncEarphones.play();
        ncEarphones.disconnect();
    }
 
}
 
http://colorscripter.com/info#e" target="_blank" style="color:#e5e5e5text-decoration:none">Colored by Color Scripter