public class ParentAdder {
public int add(int a, int b) {
return a + b;
}
}
public class ChildAdder extends ParentAdder {
public double add(double a, double b) {
System.out.println("ChildAdder.add");
return a + b;
}
}
public class OverrideMistake {
public static void main(String[] args) {
ParentAdder parentAdder = new ChildAdder();
System.out.println(parentAdder.add(3, 4));
}
}
이 코드 작성자의 기대값은 이렇습니다.
ChildAdder.add
7
하지만 실제 결과값은 다음과 같습니다.
7
실수를 찾으셨나요?
개발자의 실수는 아래의 코드입니다.
public double add(double a, double b) {}
개발자의 의도는 상위 클래스의 add 메소드를 Override 하는 것이었습니다.
하지만 매개변수형과 반환형이 달랐기 때문에 Override 되지 않았고, 그 결과값이 달라지게 된 것입니다.
이런 유형의 실수는 매우 흔합니다.
그럼에도 불구하고 발견이 쉽지 않기 때문에 치명적인 실수가 될 수 있습니다.
개발자의 실수들은 컴파일 과정에서 확인되는 것이 가장 좋습니다.
그러나 위의 경우에는 정상적으로 컴파일도 되고 실행도 됩니다.
이러한 상황을 방지하기 위해서 @Override 어노테이션을 사용하는 것입니다.
쉽게 말해 자바 컴파일러에게 '나는 상위 클래스의 메소드를 오버라이딩(Overriding) 할거야!'
라는 메모를 남기는 것이라고 생각하면 됩니다.
이제 개발자의 실수가 들어간 코드에 @Override 어노테이션을 적용해보겠습니다.
public class ChildAdder extends ParentAdder {
@Override
public double add(double a, double b) {
System.out.println("ChildAdder.add");
return a + b;
}
}
결과는 아래와 같습니다.
컴파일 과정에서 오류가 발생하여 프로그램이 실행되지 않고, 컴파일러가 친절하게 오류 원인을 제공합니다.
컴파일러 덕분에 실수를 인지할 수 있었고, 코드를 다음과 같이 수정할 수 있었습니다.
public class ChildAdder extends ParentAdder {
public int add(int a, int b) {
System.out.println("ChildAdder.add");
return a + b;
}
}
코드의 결과값은 다음과 같습니다.
드디어 개발자가 원하는 결과를 제공할 수 있게 되었습니다.
ChildAdder.add
7
코드를 잘 보시면 @Override 어노테이션이 없다는 것을 알 수 있습니다.
맞습니다. 해당 어노테이션이 존재하지 않아도 정상적으로 Override 를 할 수 있습니다.
하지만, 우리는 조금 더 안정적인 코드 작성 습관을 들여야할 필요가 있습니다.
따라서 다음과 같이 메소드를 수정합니다.
package inheritance;
public class ChildAdder extends ParentAdder {
@Override
public int add(int a, int b) {
System.out.println("ChildAdder.add");
return a + b;
}
}