public class OverridingTest {
public static void main(String[] args) {
Person person = new Person();
Child child = new Child();
Senior senior = new Senior();
person.cry();
child.cry();
senior.cry();
}
}
class Person {
void cry() {
System.out.println("흑흑");
}
}
class Child extends Person {
@Override
protected void cry() {
System.out.println("잉잉");
}
}
class Senior extends Person {
@Override
public void cry() {
System.out.println("훌쩍훌쩍");
}
}
/*
흑흑
잉잉
훌쩍훌쩍
*/
@Override는 어떤 용도인가?
이는 어노테이션(Annotation)이라는 것으로 직역하면 주석이라는 뜻이다. 이는 일반적인 주석과 다르게, 검증하는 기능을 한다. 여기서 사용된 @Override라는 어노테이션은 오버라이딩을 검증하는 기능을 한다. 코드상으로 검사했을 때 오버라이딩이 실제로 시행되지 않았다면 컴파일시 오류를 출력한다.
위 코드는 정상적으로 실행되는 것을 볼 수 있다. 부모 클래스의 메소드를 오버라이딩하는 것은 내용만을 새로 정의하는 것이므로 선언부는 부모의 것과 완벽히 동일해야 하는 것을 볼 수 있다.
프로그래머가 Person클래스의 cry메소드를 '흑흑'이라고 정의했다. 그런데 Child클래스와 Senior클래스를 만들면서 울음소리를 다르게 출력하고 싶은 것이다. 그래서 Chile클래스와 Senior클래스에서 부모의 메소드의 이름만 빌려와서 자기의 방식대로 '재정의'하였다. 이것이 오버라이딩이다.
여기서 접근 제어자를 다르게 설정해 놓은 것을 볼 수 있다. 오버라이딩에서 접근 제어자를 설정하는 규칙이 존재한다.
위에서 볼 수 있듯이 부모클래스의 접근제어자는 default로 설정되어 있다. 여기서 자식 클래스들은 default보다 같거나 더 넓은 범위의 접근제어자만 설정할 수 있으므로 default, protected, public 이 세 개의 접근 제어자는 사용이 가능하다.
부모 클래스에서 어떤 예외를 throws 한다고 하면, 자식 클래스에서는 그 예외보다 더 큰 범위의 예외를 throws할 수 없다는 것이다.
부모 클래스의 static메소드를 자식에서 같은 이름으로 정의할 수 있지만 이것은 다시 정의하는 것이 아니라 같은 이름의 static메소드를 새로 정의하는 것이다.