2026-03-29

Overriding(오버라이딩)

상속 관계에서 부모 클래스가 가진 메서드를 자식 클래스가 자신의 상황에 맞게 다시 구현하는 것

⇒ 부모가 만든 기능의 틀은 유지하되, 자식이 그 동작 내용을 바꿔서 사용하는 개념

예시

class Animal {
    void sound() {
        System.out.println("동물이 소리를 냅니다.");
    }
}

class Dog extends Animal {
    @Override
    void sound() {
        System.out.println("멍멍");
    }
}

DogAnimalsound() 메서드를 오버라이딩

오버라이딩 특징

다음 조건을 만족해야 함

  • 메서드 이름이 같아야 한다 부모와 자식의 메서드 이름이 같아야 한다.
  • 매개변수가 같아야 한다 이름만 같고 파라미터가 다르면 오버라이딩이 아니라 오버로딩이다.
  • 반환 타입이 같아야 한다 정확히는 같거나, 더 구체적인 하위 타입까지는 허용되는 경우가 있다.
  • 상속 관계여야 한다 부모-자식 관계가 아니면 오버라이딩이 아니다.
  • 접근 범위는 더 좁아질 수 없다 부모가 public인데 자식이 private로 바꾸면 안 된다.

    class Parent {
        public void hello() {}
    }
    
    class Child extends Parent {
        @Override
        private void hello() {} // 오류
    }
    

    이건 불가능

왜 중요한가?

오버라이딩은 다형성과 연결

Animal animal = new Dog();
animal.sound();

⇒ 겉으로는 Animal 타입이지만, 실제 객체는 Dog이기 때문에 Dogsound()가 실행

⇒ 실행 시점에 어떤 메서드가 호출될지 결정된다.

→ 런타임 바인딩 = 동적 바인딩

언제 쓰나?

  • 부모의 기본 동작을 자식마다 다르게 구현하고 싶을 때
  • 공통 인터페이스는 유지하면서 실제 동작은 다르게 하고 싶을 때
  • 다형성을 활용한 유연한 설계를 하고 싶을 때

예시

  • Paymentpay()
  • Animalsound()
  • Shapedraw()

⇒ 이런 구조에서 자식 클래스마다 다른 동작을 구현할 수 있다.

@Override를 쓰는 이유

필수는 아니지만 거의 항상 쓰는 것이 좋음

@Override
void sound() {
    System.out.println("멍멍");
}

이걸 쓰면 컴파일러가 “정말 부모 메서드를 재정의한 게 맞는지” 확인해준다.

예를 들어 오타가 나면 바로 잡아준다.

@Override
void soudn() {   // 오타
    System.out.println("멍멍");
}

이 경우 @Override가 없으면 그냥 새로운 메서드가 만들어질 수 있는데,

@Override가 있으면 컴파일 에러로 알려준다.

⇒ 실수를 줄이기 위해 사용하는 것

Overloading(오버로딩)

같은 이름의 메서드를 여러 개 정의하되, 매개변수를 다르게 하는 것

⇒ 이름은 같지만 전달받는 값의 타입이나 개수가 다르면, 자바는 이를 다른 메서드로 구분

예시

class Calculator {
    int add(int a, int b) {
        return a + b;
    }

    double add(double a, double b) {
        return a + b;
    }

    int add(int a, int b, int c) {
        return a + b + c;
    }
}

⇒ 모두 add라는 같은 이름을 쓰지만, 파라미터가 다르기 때문에 가능

특징

  • 메서드 이름은 같아야 한다 오버로딩은 “같은 기능군”을 묶기 위한 개념이라 이름이 같아야 한다.
  • 매개변수가 달라야 한다 다음 중 하나라도 달라야 한다.
    • 개수
    • 타입
    • 순서 예:
      void print(int a) {}
      void print(String a) {}
      void print(int a, int b) {}
      void print(String a, int b) {}
      

반환형만 다르면 안 된다

int sum(int a, int b) { return a + b; }
double sum(int a, int b) { return a + b; } // 불가능

이건 오버로딩이 아님

  • 호출할 때 자바는 매개변수 기준으로 메서드를 구분하기 때문
  • 반환형만 다르게 하는 것은 허용되지 않음

언제 결정되나?

오버로딩은 컴파일 시점에 어떤 메서드를 호출할지 결정

예시

Calculator c = new Calculator();
c.add(1, 2);
c.add(1.5, 2.5);

⇒ 컴파일러가 전달된 인자 타입을 보고 어떤 add()를 호출할지 미리 정한다.

⇒ 오버로딩은 정적 바인딩과 관련이 있다.

언제 쓰나?

  • 같은 의미의 기능을 다양한 입력값으로 처리하고 싶을 때
  • 메서드 이름을 일관되게 유지하면서 사용 편의성을 높이고 싶을 때

예시

  • println()
  • add()
  • parse()

⇒ 같은 메서드가 다양한 타입을 받아 처리하는 경우가 대표적

Override와 Overload 차이

  • 오버라이딩은 상속 관계에서 동작을 재정의
  • 오버로딩은 같은 이름의 메서드를 여러 방식으로 제공
구분 Overriding Overloading
의미 부모 메서드 재정의 같은 이름의 메서드 여러 개 정의
상속 관계 필요함 필요 없음
메서드 이름 같음 같음
매개변수 같아야 함 달라야 함
반환형 같아야 함 반환형만 달라서는 안 됨
결정 시점 런타임 컴파일 시점
관련 개념 다형성, 동적 바인딩 편의성, 정적 바인딩

요약

  • 오버라이딩 = 상속 + 재정의 + 런타임
    • 상속 관계에서 부모 클래스의 메서드를 자식 클래스가 재정의하는 것
    • 런타임에 결정
  • 오버로딩 = 같은 이름 + 파라미터 다름 + 컴파일
    • 같은 이름의 메서드를 매개변수를 다르게 해서 여러 개 정의하는 것
    • 컴파일 시점에 결정

results matching ""

    No results matching ""