[Java] 상속과 메서드 오버라이딩

코드 속의 "진돌"·2024년 3월 10일
0
post-thumbnail

✅ 메서드 오버라이딩


부모 클래스에서 상속 받은 기능을 자식 클래스에서 재정의 하는 것메서드 오버라이딩(Overriding)이라 한다.



✏️ ElectricCar

package extends1.overriding;

public class ElectricCar extends Car {

  @Override
  public void move() {
    System.out.println("전기차를 빠르게 이동합니다.");
  }

  public void charge() {
    System.out.println("충전합니다.");
  }
}

ElectricCar는 부모인 Carmove() 기능을 그대로 사용하지 않고 메서드 이름은 같지만 새로운 기능을 제공하는 move() 메서드를 새로 만들었다.

이렇게 부모 클래스의 기능을 자식 클래스에서 새로 재정의 하는 것메서드 오버라이딩이라 한다.
이제 ElectricCarmove()를 호출하면 Carmove()가 아니라 ElectricCarmove()가 호출된다.



📚 @Override

@이 붙은 부분을 애노테이션이라 한다. 애노테이션은 주석과 비슷한데, 프로그램이 읽을 수 있는 특별한 주석이라 생각하면 된다.

이 애노테이션은 상위 클래스의 메서드를 오버라이드하는 것임을 나타낸다. 오버라이딩한 메서드 위에 이 애노테이션을 붙여야 한다.

컴파일러는 이 애노테이션을 보고 메서드가 정확히 오버라이드 되었는지 확인한다. 오버라이딩 조건을 만족시키지 않으면 컴파일 에러를 발생시킨다. 따라서 실수로 오버라이딩을 못하는 경우를 방지해준다.
참고로 이 기능은 필수는 아니지만 코드의 명확성을 위해 붙여주는 것이 좋다.



✏️ CarMain

package extends1.overriding;

public class CarMain {

  public static void main(String[] args) {
    ElectricCar electricCar = new ElectricCar();
    electricCar.move();

    GasCar gasCar = new GasCar();
    gasCar.move();
  }
}



🖥️ 실행 결과

electricCar.move()를 호출했을 때 오버라이딩한 ElectricCar.move() 메서드가 실행된 것을 확인할 수 있다.



⚙️ 오버라이딩과 클래스

Carmove() 메서드를 ElectricCar에서 오버라이딩 했다.



⚙️ 오버라이딩과 메모리 구조

  1. electricCar.move()를 호출한다.
  2. 호출한 electricCar의 타입은 ElectricCar이다. 따라서 인스턴스 내부의 ElectricCar 타입에서 시작한다.
  3. ElectricCar 타입에 move() 메서드가 있다. 해당 메서드를 실행한다. 이때 실행할 메서드를 이미 찾았으므로 부모 타입을 찾지 않는다.




✅ 오버로딩(Overloading)과 오버라이딩(Overriding)


📚 메서드 오버로딩

메서드 이름이 같고 매개변수(파라미터)가 다른 메서드를 여러 개 정의하는 것메서드 오버로딩(Overloading)이라 한다.
오버로딩은 번역하면 과적인데, 과하게 물건을 담았다는 뜻이다. 따라서 같은 이름의 메서드를 여러 개 정의했다고 이해하면 된다.



📚 메서드 오버라이딩

하위 클래스에서 상위 클래스의 메서드를 재정의하는 과정을 의미한다. 따라서 상속 관계에서 사용한다. 부모의 기능을 자식이 다시 정의하는 것이다.
오버라이딩을 단순히 해석하면 무언가를 넘어서 타는 것을 말한다. 자식의 새로운 기능이 부모의 기존 기능을 넘어 타서 기존 기능을 새로운 기능으로 덮어버린다고 이해하면 된다.
오버라이딩을 우리말로 번역하면 무언가를 다시 정의한다고 해서 재정의라 한다. 상속 관계에서는 기존 기능을 다시 정의한다고 이해하면 된다. 실무에서는 오버라이딩, 메서드 재정의 둘 다 사용한다.



📚 메서드 오버라이딩 조건

  • 메서드 이름 : 메서드 이름이 같아야 한다.

  • 메서드 매개변수(파라미터) : 매개변수(파라미터) 타입, 순서, 개수가 같아야 한다.

  • 반환 타입 : 반환 타입이 같아야 한다. 단 반환 타입이 하위 클래스 타입일 수 있다.

  • 접근 제어자 : 오버라이딩 메서드의 접근 제어자는 상위 클래스의 메서드보다 더 제한적이어서는 안된다.
    예를 들어, 상위 클래스의 메서드가 protected로 선언되어 있으면 하위 클래스에서 이를 public 또는 protected로 오버라이드 할 수 있지만, private 또는 default로 오버라이드 할 수 없다.

  • 예외 : 오버라이딩 메서드는 상위 클래스의 메서드보다 더 많은 체크 예외를 throws로 선언할 수 없다. 하지만 더 적거나 같은 수의 예외, 또는 하위 타입의 예외는 선언할 수 있다.

  • static, final, private : 키워드가 붙은 메서드는 오버라이딩 될 수 없다.

    • static은 클래스 레벨에서 작동하므로 인스턴스 레벨에서 사용하는 오버라이딩이 의미가 없다. 쉽게 이야기해서 그냥 클래스 이름을 통해 필요한 곳에 직접 접근하면 된다.
    • final 메서드는 재정의를 금지한다.
    • private 메서드는 해당 클래스에서만 접근 가능하기 때문에 하위 클래스에서 보이지 않는다. 따라서 오버라이딩 할 수 없다.
  • 생성자 오버라이딩 : 생성자는 오버라이딩 할 수 없다.

profile
매일 성장하는 주니어 개발자의 기록📝

0개의 댓글