본문 바로가기

CS/JAVA

[JAVA] Override, Overriding

Inheritance > Override

 

객체 지향 프로그래밍에서 다형성(Polymorphism)과 코드의 확장성을 구현하는 핵심 원리가 바로 오버라이드(Override)입니다. 본 포스트에서는 오버라이드에 대해 알아볼 예정입니다.

오버라이드의 개념과 필요성

오버라이드란?

오버라이드는 슈퍼클래스에 정의된 메서드를 서브클래스에서 재정의, 확장 하거나, 슈퍼인터페이스에 정의된 메서드를 서브 클래스에서 재정의, 확장하는 것을 의미합니다.

 

오버라이드의 필요성

위에서 언급한대로 오버라이드(Override)는 객체 지향 프로그래밍에서 다형성과 코드의 확장성을 구현하는 핵심 원리입니다. 오버라이드가 없다면, 다형성 구현에 제약을 가져오게됩니다.

 

자동차를 예로들어 보겠습니다.

// 부모 클래스: Vehicle
class Vehicle {
    void move() {
        System.out.println("탈것이 움직입니다.");
    }
}

 

class Car extends Vehicle {
    @Override
    void move() {
        System.out.println("자동차는 네 바퀴로 달립니다.");
    }
}

Vehicle은 탈것으로 움직인다는 개념이 존재했지만 자식 클래스 Car는 move()를 재정의하여 자신만의 자동차는 네 바퀴로 달린다는 move()를 만들어냈습니다. 


오버라이드의 조건

클래스에서 오버라이딩

  1. 서브클래스 C는 슈퍼클래스 A를 상속받아야함.
  2. 슈퍼클래스 A의 mA를 상속받아 만들어진 서브클래스 C의 mC는 새로운 구현이 되어야합니다.
  3. 시그니처 호환성
    1. 메서드 이름이 동일해아함. 
    2. 매개변수 목록(개수, 순서, 타입)이 동일함
    3. 정확히는 mC의 시그니처가 mA의 서브 시그니처여야함
    4. 반환타입은 상위 반환타입과 동일하거나 하위 타입이어야함(Java SE 5.0 부터)
    5. 접근 제한자는 상위의 접근제한자보다 더 넓거나 동일한 접근제한자를 가져야합니다.
  4. 오버라이딩된 메서드가 static 메서드인 경우 런타임 에러가 발생
  5. final 메서드 오버라이딩 불가
  6. private 메서드는 서브클래스에 상속되지 않습니다.
  7. 조상보다 더 큰 예외를 던질 수 없음.
  8. 리턴 타입이 같아야한다.

 

인터페이스에서 오버라이딩

  1. 디폴트 메서드는 클래스 내의 메서드에의해 선택적으로 오버라이드 될 수 있음.
  2. 클래스에 상속된 구체적인 메서드는 인터페이스에 선언된 추상 메서드를 오버라이드함.
  3. 인터페이스는 private또는 static메서드를 슈퍼 인터페이스로부터 상속하지 않음.
  4. 오버라이드된 디폴트 메서드는 슈퍼인터페이스 이름으로 한정된 super 키워드를 사용하여 접근 가능
  5. 다중 상속된 메서드의 처리
    두 개의 다른 디폴트 메서드가 일치하는 시그니처로 서브인터페이스에 상속되는 경우 컴파일 에러가 발생

@Override(오버라이드 어노테이션)의 역할과 중요성

슈퍼클래스A를 상속받은 서브클래스C에서 mA를 재정의하여 mC를 만들었다면 자동으로 오버라이딩 될텐데 왜 '@Override'어노테이션을 사용하나요?

  1. 컴파일 타임 오류 방지
    컴파일러에게 상위클래스 또는 인터페이스의 메서드를 오버라이드 하는 것 이라는 점을 알려 오버라이딩 규칙에서 벗어날 경우에 컴파일 오류를 발생시켜 개발자에게 알려줍니다.
  2. 코드 가독성 및 유지보수성 증가
    @Override 어노테이션은 다른 개발자들이 코드를 읽을 때 오버라이딩된 메서드임을 명확하게 인지할 수 있어서 가독성이 증가합니다.
public class Vehicle {
	public void move(int velocity) {
		System.out.println("탈 것이 "+velocity+"의 속도로 움직이고 있습니다.");
	}
}

public class Car extends Vehicle {
	public void move(double velocity) {
		System.out.println("자동차가 " + velocity +"의 속도로 움직이고 있습니다.");
	}
}

public class Solution {
	public static void main(String args[]) {
		Vehicle vehicle = new Vehicle();
		vehicle.move(1);
		
		Vehicle car_noex = new Car();
		car_noex.move(1);
		
		Car car = new Car();
		car.move(1.22);
	}
}

위는 어노테이션 없이 오버라이드한 코드예제입니다.

move의 매개변수를 int에서 float로 변경했지만 오류는 나지 않습니다. 이것은 오버로딩이기 때문입니다. 이렇듯 오버라이딩을 할 때는 @Override 어노테이션을 적용해서 컴파일러가 해당 메서드는 오버라이딩을 할 것임을 명시해줘야 합니다.

 

어노테이션을 적용하면 컴파일러가 오류를 띄워주게 됩니다.

출처

[The Java Language Specification Java SE 17 Edition] (https://docs.oracle.com/javase/specs/jls/se17/jls17.pdf)

[정보통신용어기술해설] (http://www.ktword.co.kr/test/view/view.php?no=2673)