메소드 오버라이딩(메소드 재정의, Overriding)
자식이 부모 클래스의 필드, 메소드들을 상속받지만, 그 중에서는 재정의가 필요한 메소드가 있을 수도 있습니다.
자바는 상속된 메소드 중 일부를 자식 클래스에서 다시 수정하여 사용할 수 있게끔 해 줍니다.
이 기능을 메소드 오버라이딩(Overriding) 이라고 합니다.
메소드를 오버라이딩 할 시 몇 가지 중요한 주의사항이 있습니다.
재정의할 부모의 메소드와 동일한 메소드명, 리턴 타입, 매개 변수 리스트로 작성해야 한다.
메소드의 접근 제한자는 부모의 것보다 더 제한이 강한 것을 사용할 수 없다. (예를 들어 부모의 메소드가 public 이었는데, 자식이 오버라이딩 할 때 private로 할 수 없음)
새로운 Exception을 throws 할 수 없다.
일단 예시를 먼저 확인해 보겠습니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public Class Parent {
int CalCul(int num){ // 부모의 메소드
return num * 3;
}
}
public Class Child extends Parent {
@Override
int CalCul(int num) { // 메소드 재정의
System.out.print("결과는 "+num+" 입니다.");
}
public static void main(String[] args) {
Child ch = new Child();
ch.CalCul(5); //오버라이딩된 자식 객체의 메소드 CalCul이 호출됨
}
}
[> output] 결과는 5 입니다.
자식 클래스에서 부모의 CalCul 메소드를 재정의하는 상황입니다.
@Override 어노테이션은 컴파일러에게 메소드가 정확하게 오버라이딩 되었는지 확인을 요청하는 것으로,
생략되도 상관은 없으나 개발자의 실수를 체크해 주므로 프로그램 안정성에 도움을 줍니다.
그리고 재정의한 곳의 선언부를 보면 부모 메소드와 리턴 타입(int)과 메소드명(CalCul), 매개변수 리스트(int …) 이 모두 동일한 것을 알 수 있습니다.
이렇게 재정의가 되었다면, 기존 부모의 메소드는 가려지게 됩니다.
따라서 main 메소드 등에서 자식 객체를 생성해 해당 메소드를 호출하면, 오버라이딩된 자식 메소드를 호출하게 됩니다.
부모 메소드 호출
그러나 부모 메소드는 가려진 것 뿐이므로, 자식 클래스 내부에서 가려진 부모 클래스의 메소드를 사용할 수 있는 방법이 마련되어 있습니다.
이 때도 역시 부모를 나타냈던 super를 이용하는데요, 예시를 확인해 보겠습니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public Class Parent {
int CalCul(int num){ // 부모의 메소드
return num * 100;
}
}
public Class Child extends Parent {
@Override
int CalCul(int num) { // 메소드 재정의
return num * 3;
}
int CalCulTWO(int num){
return super.CalCul(num);
// super.CalCul(num); 으로 부모 객체의 CalCul 메소드를 호출
}
public static void main(String[] args) {
Child ch = new Child();
System.out.print("자식 메소드 실행값 :"+ch.CalCul(5)+"\n부모 메소드 실행값 :"
+ch.CalCulTWO(5));
}
}
[> output]
자식 메소드 실행값 : 15
부모 메소드 실행값 : 500
이처럼 부모의 메소드를 호출하고 싶으면, 자식 클래스 내부에서 super.(부모 메소드명); 으로 선언하면 됩니다.
final 클래스와 final 메소드
final 키워드는 클래스, 필드, 메소드 선언시에 사용됩니다. final이 붙으면 최종적이며, 수정될 수 없음을 의미합니다. 그래서 상수 선언시에 많이 볼 수 있습니다.
이 final 키워드가 클래스나 메소드에 붙게 되면, 각각 상속할 수 없고, 오버라이딩 할 수 없습니다.
1
2
public final class Parent {.....}
public class Child extends Parent {.....} // 불가능한 선언!
parent 클래스는 final 키워드가 붙어 있으므로, 어떤 곳에서도 상속 불가능합니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public Class Parent{
..........
public final void method(){
System.out.print("수정할 수 있을까?");
}
.....
public Class Child extends Parent{
...
@Override
public void method(){ /// 불가능한 선언. 컴파일 에러이다.
System.out.print("수정 못 한다.");
}
}
또한 이와 같이 자식 클래스에서 final로 선언된 부모의 메소드를 오버라이딩 하는 것도 불가능합니다.