본문 바로가기

객체 지향 프로그래밍에서 오버로딩(Overloading)과 오버라이딩(Overriding) 차이점

면강 2023. 4. 24.

객체지향 프로그래밍에서 오버로딩과 오버라이딩은 굉장히 중요한 개념이다. 이름은 비슷하게 생겼지만 그 사용처는 전혀 다른 기능인데 각각에 대해 설명하고 비교해 본다.

 


오버로딩(Overloading)

 

오버로딩은 객체 지향 프로그래밍에서 메서드의 이름은 같지만, 매개변수의 수, 타입, 순서 등이 다른 여러 개의 버전을 정의하는 것이다. 즉, 같은 이름의 메서드를 여러 개 정의할 수 있는 기능을 의미한다. 예를 들어 다음과 같이 add라는 이름의 메소드를 여러 개 정의할 수 있다.

 

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

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

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


위 예제에서 Calculator 클래스의 add 메서드는 이름은 같지만, 매개변수의 종류, 수, 순서, 반환형이 서로 다른 세 가지 버전이 존재한다. 이렇게 오버로딩을 사용하면 같은 기능을 하는 메서드에 다른 이름을 부여하지 않아도 되기 때문에, 코드의 가독성과 재사용성을 높일 수 있다.

메서드를 호출할 때는 전달한 인수의 수와 타입으로 적합한 메소드를 자동으로 선택한다. 예를 들어 Calculator 클래스의 add 메소드를 호출할 때 전달하는 인수의 수와 타입에 따라서 아래와 같이 선택된다.

 

Calculator calc = new Calculator();

int result1 = calc.add(1, 2);         // add(int a, int b) 호출
int result2 = calc.add(1, 2, 3);      // add(int a, int b, int c) 호출
double result3 = calc.add(1.0, 2.0);  // add(double a, double b) 호출


위 예제에서 calc.add(1, 2)add(int a, int b)를 호출하고, calc.add(1, 2, 3)add(int a, int b, int c)를 호출하고 calc.add(1.0, 2.0)add(double a, double b)를 호출하게 된다.

오버로딩은 메서드의 이름을 공유하는과 동시에 메소드의 사용성과 가독성을 높일 수 있는 객체 지향 프로그래밍의 중요한 개념 중 하나이다.

 


오버라이딩(Overriding)

 

오버라이딩은 객체 지향 프로그래밍에서 상위 클래스에서 정의된 메서드를 하위 클래스에서 재정의하는 것을 의미한다. 상위 클래스에 있는 메소드를 하위 클래스에서 재정의하여 사용하는 이유는 하위 클래스에서 상위 클래스의 메소드와는 다른 기능을 구현하기 위함이다.

오버라이딩은 다형성(polymorphism)을 구현하기 위한 기능 중 하나로 동일한 이름의 메소드를 다양한 클래스에서 다양한 구현을 제공할 수 있도록 한다. 오버라이딩을 사용하기 위해서는 다음과 같은 규칙을 따라야 한다.

 

메서드의 이름, 매개변수의 개수와 타입, 반환 타입이 모두 일치

접근 지정자는 상위 클래스의 메서드와 같거나 더 넓은 범위로 설정할 것. 예를 들어, 상위 클래스의 메서드가 public으로 선언되어 있다면, 하위 클래스에서는 public이나 protected로 오버라이딩할 수 있습니다.

final, static, private 메서드는 오버라이딩이 불가능

상위클래스의 메서드가 public으로 선언되어 있는 경우 하위 클래스는 public 또는 protected로 오버라이딩 할 수 있다.

 

Copy code
public class Animal {
    public void speak() {
        System.out.println("Animal speaks");
    }
}

public class Cat extends Animal {
    @Override
    public void speak() {
        System.out.println("Meow!");
    }
}

public class Dog extends Animal {
    @Override
    public void speak() {
        System.out.println("Woof!");
    }
}

 

위 예제에서 Animal 클래스에 있는 speak() 메서드를 Cat 클래스와 Dog 클래스에서 각각 오버라이딩하고 있다. Cat 클래스에서는 "Meow!"를 출력하고, Dog 클래스에서는 "Woof!"를 출력하게 구현하였다.

 

이렇게 하위 클래스에서 상위 클래스의 메서드를 재정의하면 상위 클래스의 메소드는 가려지고 하위 클래스의 메소드가 호출된다. 즉, 오버라이딩을 사용하면 하위 클래스에서 상위 클래스의 메소드를 사용하면서 더 구체적인 구현을 제공할 수 있다.

 


 

위 두 내용을 종합하면 오버로딩은 같은 이름의 메소드를 다양한 매개변수로 정의하는 것이고 오버라이딩은 상위 클래스의 메소드를 하위 클래스에서 재정의하는 것이다.