오버라이딩이란?
부모 클래스로부터 상속받은 메서드의 내용을 변경하는 것
상속받은 메서드를 그대로 사용하기도 하지만, 자신에 맞게 변경해야하는 경우 오버라이딩 한다
class Point {
int x;
int y;
string getLocatin(){
return "x :" + x + "y :" + y;
}
}
class Point3D extends Point {
int z;
string getLocatin(){
return "x :" + x + "y :" + y + "z :" + z;
}
}
오버라이딩의 조건
오버라이딩은 메서드의 내용만을 새로 작성하는 것이므로 메서드의 선언부는 부모와 완전히 일치해야 한다
- 이름이 같아야 함
- 매개변수가 같아야 함
- 반환 타입이 같아야 함
다만 접근 제어자와 예외는 제한된 조건하에 다르게 변경 가능하다
1. 접근 제어자는 소장 클래스의 메서드보다 좁은 범위로 변경할 수 없다
만약 부모 클래스에 정의된 메서드의 접근 제어자가 protected라면,
이를 오버라이딩 하는 자식 클래스의 메서드는 접근 제어자가 protected 또는 public 이어야 한다
대부분의 경우 같은 범위의 접근 제어자를 사용한다
접근 제어자의 접근범위를 넓은 것에서 좁은 것 순으로 나열하면 public, protected, (default), private 이다.
2. 조상 클래스의 메서드보다 많은 수의 예외를 선언할 수 없다
class Parent {
void parentMethod() throws IOException, SQLException{
...
}
}
class Child extends Parent {
void parentMethod() throws IOException {
...
}
...
}
위 예시를 보면 Child 클래스의 parentMethod()에 선언된 예외의 개수가 부모인 Parent 클래스의 parentMethod()에 선언된 예외의 개수보다 적으므로 바르게 오버라이딩 되었다
주의해야할 점은 단순히 선언된 예외의 개수의 문제가 아니라는 것
class Child extends Parent{
void parentMethod() throws Exception{
...
}
...
}
만약 위와 같은 경우 부모보다 적은 개수의 예외를 선언한 것 처럼 보이지만,
Exception은 모든 예외의 최상위 부모 클래스 이므로 가장 많은 개수의 예외를 던질 수 있도록 선언한 것이다
그래서 잘못된 오버라이딩이 된다
부모 클래스의 메서드를 자식 클래스에서 오버라이딩 할 때
1. 접근 제어자를 부모 클래스의 메서드보다 좁은 범위로 변경할 수 없다
2. 예외는 조상 클래스의 메서드보다 많이 선언할 수 없다
3. 인스턴스 메서드를 static메서드로 또는 그 반대로 변경할 수 없다
오버로딩 vs. 오버라이딩
오버로딩 - 기존에 없는 새로운 메서드를 추가하는 것
오버라이딩 - 조상으로부터 상속받은 메서드의 내용을 변경하는 것
class Parent {
void parentMethod() {
...
}
}
class Child extends Parent {
void parentMethod() {} //오버라이딩
void parentMethod(int i) {} //오버로딩
void childMethod() {}
void childMethod(int i) {}
void childMethod() {} //중복 정의로 인한 에러. already defined in Child
}
super
부모 클래스로부터 상속받은 멤버를 참조하는데 사용되는 참조 변수
멤버변수와 지역변수의 이름이 같을 때 this를 붙여서 구별했듯이 상속받은 멤버와 자신의 멤버와 이름이 같을 때는 super를 붙여서 구별할 수 있음
부모 클래스로부터 상속받은 멤버도 자식 클래스 자신의 멤버이므로 super대신 this를 사용할 수 있음
부모 클래스의 멤버와 자손클래스의 멤버가 중복 정의되어 서로 구별해야하는 경우에만 super를 사용하는 것이 좋다
부모의 멤버와 자신의 멤버를 구별하는데 사용된다는 점을 제외하고는 super와 this는 근본적으로 같음
모든 인스턴스 메서드에는 자신이 속한 인스턴스의 주소가 지역변수로 저장되는데, 이것이 참조변수인 this와 super의 값이 된다
static 메서드(클래스메서드)는 인스턴스와 관련이 없다
그래서 this와 마찬가지로 super역시 static 메서드에서는 사용할 수 없고 인스턴스 메서드에서만 사용할 수 있다
class SuperTest {
public static void main (String args[]){
Child c = new Child();
c.method();
}
}
class Parent {
int x = 10;
}
class Child extends Parent {
void method() {
System.out.println("x=" + x);
System.out.println("this.x=" + this.x);
System.out.println("super.x=" + super.x);
}
}
결과
x = 10
this.x = 10
super.x = 10
class SuperTest2 {
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);
}
}
결과
x = 20
this.x = 20
super.x = 10
이처럼 부모 클래스에 선언된 멤버변수와 같은 이름의 멤버변수를 자식 클래스에서 중복해서 정의하는 것이 가능하며
참조변수 super를 이용해서 서로 구별할 수 있다
super() - 조상 클래스의 생성자
this()와 마찬가지로 super()역시 생성자
this()는 같은 클래스의 다른 생성자를 호출하는데 사용되지만
super()는 부모 클래스의 생성자를 호출하는데 사용됨
생성자의 첫 줄에서 부모클래스의 생성자를 호출해야 하는 이유는 자식 클래스의 멤버가 부모의 멤버를 사용할 수도 있으므로 부모의 멤버들이 먼저 초기화되어야 하기 때문
따라서 Object 클래스를 제외한 모든 클래스의 생성자는 첫 줄에 반드시 자신의 다른 생성자 또는 부모의 생성자를 호출해야한다.
그렇지 않으면 컴파일러가 super();를 자동적으로 추가함
'Language > Java' 카테고리의 다른 글
[Java] 객체지향 프로그래밍 - 제어자 (0) | 2024.04.05 |
---|---|
[Java] 객체지향 프로그래밍 - package와 import (0) | 2024.04.05 |
[Java] 객체 지향 프로그래밍 - 상속 (0) | 2024.04.03 |
[Java] JsonArry 형태의 문자열을 List<VO>객체로 변환하기 (0) | 2023.10.12 |
[Java] Optional이란? (0) | 2023.09.04 |