지금까지 객체 지향에 대해서 알아보면서 꾸준히 등장하는 요소가 있었다 추상화, 다형성, 상속 모든 부분에 걸쳐있는 가장 객체지향의 가장 중요한 요소 중 하나인
오버로딩(Overloading) 과 오버리이딩(Overriding)이다.
오늘은 이 중에서 오버라이딩에 대해서 알아보자.
오버라이딩을 간단하게 설명하면
상속 관계를 가진 클래스들에서 부모 클래스의 메서드를 자식 클래스가 재정의하는 것
여러번 코드로 봐 왔기에 이미 알고 있겠지만
그래도 다시한번 간단한 예를 들어보면
public class Employee{
public double salary(double time, int day){
return time * day * 10000d;
}
}
public class NightTimeWorker extends Employee{
@Override
public double salary(double time, int day){
return super.salary(time, day) * 1.2;
}
}
NightTimeWorker 클래스가 Employee클래스를 상속하고
Employee클래스의 메서드인 salary를 재정의하여 20%의 야간수당을 받을 수 있도록 작성하였다.
그렇다면 여기서 의문이 드는 사람도 있을것이다.
"그냥 NightTimeWorker에 salary메서드를 만들어서 작성하면 좋을텐데 굳이 상속을 받고 오버라이딩(재정의)를 해서 만들어야 할까?"
Java에서 오버라이딩을 쓰는 이유에 대해서는 이전에도 말했듯이 코드 재사용성을 늘리고, 유지보수성과 확장성을 높이고 다형성을 통해 통일된 인터페이스를 제공할 수 있다는 점이 있다.
그리고 위의 이점들을 모두 가지고 있는
제가 생각하기에 오버라이딩을 사용하는 가장 중요한 개념인 "동적 바인딩(Dynamic Binding)"이 있다.
public static void printSalary(Employee employee, double time, int day){
double salary = employee.salary(time, day)
System.out.println(salary)
}
public static void main (String[] args){
printSalary(new Employee(), 8.2, 22)
printSalary(new NightTimeWorker(), 8.2, 22)
}
월급을 출력하는 메서드 printSalary를 만들고 main에서 printSalary만을 이용해서 각각 출력했다.
출력 결과는 각각 Emplyee의 월급, NightTimeWorker의 월급이 출력될 것이다.
이것이 가능한 이유는 Java에서는 메서드 호출이 런타임에 동적으로 결정되고, 객체의 실제 타입에 따라 호출할 메서드가 선택되기 때문인데 이 내용에 대한 세부사항은 나중에 다른 포스트로 다루기로 하고
지금 중요한것은 만약 NigthTimeWorker클래스가 오버라이딩을 하지 않고 독자적으로 메서드를 작성했다면 NightTimeWorker에 대한 print메서드를 따로 만들어줘야 할 것이다.
그리고 Employee를 상속하는 객체들이 늘어나면 늘어날 수록 코드가 복잡해지고 유지보수가 힘들어지는 원인이 될 것이다.
오버라이딩을 할 때 주의해야할 점이 몇가지 있는데 간단히 요약하면
기존 메서드의 시그니처를 바꿔서는 안되며, 메서드의 동작만을 재정의 해야한다.
접근제어자를 더 넓은 범위(예,protected -> public)으로 변경은 가능하지만 더 좁은 범위(예,protected -> private)으로 변경은 불가능하다.
final 및 static으로 선언된 메서드는 오버라이딩 할 수 없다. final의 경우 하위 클래스에서 재정의 할 수 없으며, static의 경우 클래스레벨에서 선언되기에 오버라이딩의 대상이 아니다.(JVM 메모리 구조 참고)
정답은 "사용하는 것이 좋다." 이다.
@무엇무엇을 '어노테이션' 이라고 부르는데 이는 코드 실행시 컴파일러에게 특별한 정보를 전달하는데 사용된다.
어노테이션을 사용하지 않아도 오류가 발생하지는 않는다.
하지만 @Override를 사용할경우 컴파일러는 해당 메서드가 오버라이딩된 메서드임을 인식하고 오버라이딩이 잘못된 경우(예를 들면, 오버라이딩의 대상인 메서드의 파라미터가 추가되었다거나) 경고하여 오류를 방지할 수 있다.
역시나 간단한 개념이라고 생각했지만 머리속에서 끄집어 내려 하니 쉽지 않았다. 잘 알고있다고 착각하지 말고 꾸준히 공부하고 생각하도록 해야겠다.
오늘도 부족한 글 봐주셔서 정말 감사하다(?)... 감사합니다!