조상 클래스로부터 상속받은 메소드의 내용을 변경하는 것을 오버라이딩이라고 한다
상속받은 메소드를 그대로 사용할 수도 있지만, 자식 클래스 본인에 맞게
메소드의 내용을 변경해야하는 경우 오버라이딩을 한다.
class Parent {
void speak() {
System.out.println("I'm Parent");
}
}
class Child extends Parent {
@Override
void speak() {
System.out.println("I'm Child);
}
}
@Override 어노테이션은 메소드가 오버라이딩된 메소드임을
한 눈에 알아볼 수 있게 명시적으로 선언해주는 것입니다.
어노테이션이 없어도 컴파일 에러는 나지 않습니다
오버라이딩은 메소드의 내용만을 새롭게 작성하는 것이므로 부모 클래스 메소드와 선언부가 완전히 일치해야 한다
다만, 접근 제어자 와 예외 는 제한된 조건 하에서 다르게 변경이 가능하다.
만일 조상 클래스 메소드의 접근 제어가 protected라면
오버라이딩한 메소드는 protected 혹은 public이어야 한다.
참고로 접근 제어자의 접근 범위는 넓은 순부터
public - protected - default - private 이다.
class Parent {
void parentMethod() throws IOException, SQLException { ... }
}
class Child1 extends Parent {
@Override
void parentMethod() throws IOException { ... }
}
class Child2 extends Parent {
@Override
void parentMethod() throws Exception { ... }
}
Child1 클래스의 parentMethod는 부모 클래스의 예외보다 개수가 적으므로 바르고 오버라이딩된 것이다.
Child2 클래스의 parentMethod 역시 부모 클래스의 예외보다 개수가 적다. 그러나 잘못된 오버라이딩이다!!
왜냐하면 Exception은 모든 예외의 최고 조상이므로 가장 많은 개수의 예외를 던질 수 있도록 선언된 것이다.
즉, 단순히 선언된 예외의 개수의 문제가 아니라는 것을 주의해야 한다.
오버라이딩의 조건 중 반환타입이 같아야 하는 조건이 있다.
그러나 JDK 1.5부터 추가된 공변 반환 타입을 사용하면 다른 리턴 타입을 가질 수 있다.
다만, 오버라이딩을 할 메소드 리턴 타입의 서브 타입이어야 한다.
class Parent {
Parent method() { return new Parent(); }
}
class Child extends Parent {
@Override
Child method() { return new Child(); }
}
공변 반환 타입이 생기기 전에는 원래 반환 타입으로 리턴을 해주었어야 해서
저 경우에는 Child 클래스의 오버라이딩 메소드도 Parent 타입으로 반환 후 메소드를 호출한 곳에서 Child 타입으로 변환을 해주었어야 했다.
그러나 공변 반환 타입을 사용하면 바로 서브 클래스 타입으로 반환을 할 수 있기에 번거로운 형변환 코드를 줄일 수 있다.
조상 클래스에서 정의된 static 메소드를
자식 클래스에서 같은 이름의 static 메소드를 정의할 수 있나?
답은 가능하다이다.
그러나 이것은 오버라이딩으로 보지 않고 각 클래스에 별개의 static 메소드로 본다
추가로 오버라이딩 시 인스턴스 메소드를 static 메소드로 혹은 그 반대로도 불가능하다
오버로딩과 오버라이딩을 많이 혼동하지만 완전히 다르고 차이도 명백하다.
class Parent {
void parentMethod() { }
}
class Child {
void parentMethod() { } // 1
void parentMethod(int i) { } // 2
void childMethod() { } // 3
void childMethod(int i) { } // 4
}