오버라이딩이란?
조상 클래스로부터 상속받은 메서드의 내용을 변경하는 것을 오버라이딩이라고 한다.
상속 받은 메서드를 자손 클래스 자신에 맞게 변경해야하는 경우에 이를 활용한다.
오버라이딩 조건
자손 클래스에서 오버라이딩하는 메서드는 조상 클래스의 메서드와
-이름이 같아야 한다.
-매개변수가 같아야 한다.
-반환타입이 같아야 한다.
즉 오버라이딩은 메서드의 내용만을 새로 작성하는 것이므로 메서드의 선언부는 조상의 것과 완전히 일치해야 한다.
다만 접근 제어자(access modifier)와 예외(exception)는 제한된 조건 하에서만 다르게 변경할 수 있다.
- 접근 제어자 : 조상 클래스의 메서드보다 좁은 범위로 변경 할 수 없다.
- 예외 : 조상 클래스의 메서드보다 많은 수의 예외를 선언할 수 없다.
-static 메소드 : 인스턴스 메소드를 static 메서드로 또는 그 반대로 변경할 수 없다.
만약 조상 클래스에서 정의된 static 메서드를 자손 클래스에서 똑같은 이름의 static 메서드로 정의한다면?
=>이는 각 클래스에서 별개의 static메서드를 정의한 것일 뿐 오버라이딩으로 볼 수 없다. 따라서 호출할 때에는 '클래스.메서드이름()'으로 사용한다.
오버로딩 vs 오버라이딩
자주 헷갈리는 두 개념이지만, 사실 그 차이는 명백하다. 오버로딩은 기존에 없는 새로운 메서드를 추가하는 것이고, 오버라이딩은 조상으로부터 상속받은 메서드의 내용을 변경하는 것이다.
오버로딩(overloading) - 기존에 없는 새로운 메서드를 정의하는 것 => 매개변수의 차이로 구분하여 새로운 메서드 정의
오버라이딩(overriding) - 상속받은 메서드의 내용을 변경하는 것 => 선언부가 완전 일치하고 메서드의 내용만 변경
super
super는 자손 클래스에서 조상 클래스로부터 상속받은 멤버를 참조하는데 사용되는 참조변수이다.
따라서 상속받은 멤버와 자신의 멤버가 이름이 같을 때는 super를 붙여서 구별할 수 있다.
(참고로 앞서 정리한 this는 자기 자신을 가르키는 참조변수)
조상 클래스로부터 상속받은 멤버도 자손 클래스 자신의 멤버이므로 super대신 this를 사용할 수 있지만, 조상 클래스의 멤버와 자손 클래스의 멤버가 중복 정의되어 서로 구별해야만 하는 경우에만 super를 사용하는 것이 좋다.
static메서드는 인스턴스와 관련이 없기때문에 super역시 static메서드에서는 사용할 수 없고 인스턴스메서드에서만 사용할 수 있다.
예제)
public class SuperTest {
public static void main(String[] args) {
Child c = new Child();
c.method();
}
}
class Parent{
int x=10;
}
class Child extends Parent{
int x=20;
void method() {
System.out.println("x=" + x);
System.out.println("this.x=" + this.x);
System.out.println("super.x=" + super.x);
}
}
이처럼 조상 클래스에 선언된 멤버변수와 같은 이름의 멤버변수를 자손 클래스에서 중복해서 정의할 수 있고 super를 통해 서로 구별한다.
뿐만아니라 메서드 역시 super를 써서 호출할 수 있다. 특히 조상 클래스의 메서드를 자손 클래스에서 오버라이딩한 경우에 super를 사용한다.
super( ) - 조상 클래스의 생성자
this()와 마찬가지로 super역시 생성자이다. 다만 super( )는 조상 클래스의 생성자를 호출하는데 사용된다.
자손 클래스의 인스턴스를 생성하면, 자손의 멤버와 조상의 멤버가 모두 합쳐진 하나의 인스턴스가 생성된다. 그래서 자손 클래스의 인스턴스가 조상 클래스의 멤버들을 사용할 수 있는 것인데, 이 때 조상 클래스 멤버의 초기화 작업이 수행되어야 하기 때문에 자손 클래스의 생성자에서 조상 클래스의 생성자가 호출되어야 하고 무조건 첫 줄에 호출되어야 한다.
이와 같은 조상 클래스 생성자의 호출은 클래스의 상속관계를 올라가면서 최고 조상인 Object클래스의 생성자인 Object( )까지 가서야 끝이 난다. 따라서 Object클래스를 제외한 모든 클래스의 생성자는 첫 줄에 자신의 다른 생성자 또는 조상의 생성자를 호출해야 한다.
그렇지 않으면 컴파일러는 생성자의 첫 줄에 'super( );'를 자동으로 추가한다.
'Java > 객체지향프로그래밍' 카테고리의 다른 글
[Java] 다형성(polymorphism) - 코딩밥상 (0) | 2023.02.09 |
---|---|
[Java] 제어자(modifier) - 코딩밥상 (0) | 2023.02.09 |
[Java] 상속(Inheritance) - 코딩밥상 (0) | 2023.02.08 |
[Java] 초기화 블럭(initialization block) - 코딩밥상 (0) | 2023.02.07 |
[Java] 생성자(Constructor) - 코딩밥상 (0) | 2023.02.07 |