본문 바로가기
Language/Java

[Java] 오버라이딩 - 오버로딩과 오버라이딩의 차이

by 계범 2022. 3. 4.

오버라이딩(overriding)

오버라이딩이란

조상 클래스로부터 상속받은 메서드의 내용을 재정의(변경)하는 것을 오버라이딩이라고 한다.

 

상속받은 메서드를 그대로 사용할 수도 있지만, 자손 클래스에 맞게 재정의해서 쓸 경우에 오버라이딩이라고 한다.

override의 사전적 의미 '~위에 덮어쓰다(overwrite)'

 

class Point{
	int x;
    int y;
    
    String getLocation(){
    	return "x : " + x + ", y : " + y;
    }
}

class Point3D extends Point{
	int z;
    // 오버라이딩
    String getLocation(){
    	return "x : " + x + ", y + " + y + ", z : " + z;
    }
}

오버라이딩의 조건

  • 메서드 이름이 같아야 한다.
  • 매개변수가 같고, 반환타입이 같아야 한다.(다르면 오버로딩)
  • 접근 제어자는 조상 클래스의 메서드보다 좁은 범위로 변경할 수 없다.
    • 조상이 protected면, 자손은 protected 나 public 이어야함.
    • 접근 제어자 넓은 것에서 좁은 순 나열 public, protected , (default), private
  • 조상클래스의 메서드보다 많은 수의 예외를 선언할 수 없다.
    • 조상 클래스가 IOException, SQLException이 선언되어있다면, 자손은 그보다 작은 수의 예외를 선언해야한다.
    • 만약 자손이 Exception예외가 걸려있다면, 적어보이지만 Exceptioon은 예외의 최고 조상으로 가장 많은 개수의 예외를 던질 수 있도록 선언한것이므로 잘못된 오버라이딩이다.
  • 인스턴스메서드를 static메서드로 또는 그 반대로 변경할 수 없다.

 

오버로딩 vs 오버라이딩

오버로딩(overloading) 기존에 없는 새로운 메서드를 정의(new)
오버라이딩(overriding) 상속받은 메서드의 내용을 변경(change,modify)

오버로딩 참조

2022.03.02 - [Language/Java] - [Java] 오버로딩(overloading)

 

super

super는 자손 클래스에서 조상 클래스로부터 상속받은 멤버를 참조하는데 사용되는 참조변수이다.

멤버변수와 지역변수의 이름이 같을 때 this를 붙여서 구별했듯이

상속받은 멤버와 자신의 멤버와 이름이 같을 때 super를 붙여서 구별할 수 있다.

 

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
**/

static은 인스턴스와 관계없으니 static엔 사용 불가능

 

super()

this()와 마찬가지로 super() 역시 생성자이다.

this()는 같은 클래스의 다른 생성자를 호출하는데 사용되지만,

super()는 조상 클래스의 생성자를 호출하는데 사용된다.

 

자손 클래스의 인스턴스가 조상 클래스의 멤버들을 사용할때,

조상 클래스 멤버의 초기화 작업이 수행되어야하기 때문에

자손 클래스의 생성자에서 조상 클래스의 생성자가 호출되어야 한다.

 

자손 생성자의 첫 줄에서 조상클래스의 생성자를 호출해야하는 이유는 자손 클래스의 멤버가 조상 클래스의 멤버를 사용할 수도 있으므로 먼저 초기화되어 있어야 한다.

외와 같은 조상 클래스 생성자의 호출은 상속관계를 거슬러 올라가면서 최고 조상인 Object클래스의 생성자인 Object()까지 가서야 끝이 난다.

 

만약 첫줄에 없으면 컴파일러가 생성자의 첫 줄에 'super();'를 자동적으로 추가해준다.

하지만, 조상 클래스에 super()에 해당하는 기본 생성자가 존재하지 않는다면, 컴파일 에러가 발생한다.

 

class PointTest {
	public static void main(String args[]) {
		Point3D p3 = new Point3D(1,2,3);
	}
}

class Point {
	int x;	
	int y;

	Point(int x, int y) {
		this.x = x;
		this.y = y;
	}

	String getLocation() {
		return "x :" + x + ", y :"+ y;
	}
}

class Point3D extends Point {
	int z;

	Point3D(int x, int y, int z) {
		// Point(x,y)에 해당하는 super(x,y) 가 추가되어야함! 아니면 컴파일 에러
		this.x = x;
		this.y = y;
		this.z = z;
	}

	String getLocation() {	// 오버라이딩
		return "x :" + x + ", y :"+ y + ", z :" + z;
	}	
}

해당 자식 생성자에서 첫줄에 조상 생성자를 호출해야하는데 없기때문에 컴파일러가 조상의 기본생성자를 자동적으로 추가해준다. 하지만,  조상의 기본 생성자 Point()는 없기에 컴파일러 에러가 발생한다.

 

해당 문제를 해결해주기 위해선,

조상 클래스에 기본 생성자를 넣던가

아니면 자손 클래스의 생성자 첫줄에 조상클래스의 생성자 Point(x,y)에 해당하는 super(x,y)를 추가해야한다.

 

참조

'Java의 정석' 책

댓글