언어/자바의 정석

[자바의 정석] Chapter 6 객체 지향 프로그래밍 요약(4) - 오버로딩

chan10 2021. 2. 4. 09:06

오버로딩(overloading)

오버로딩이란?

한 클래스에서 메소드도 구별이 되어야 하기에 각각 다른 이름을 가져야 하나 같은 이름의 메소드가 있더라도 매개 변수 또는 타입이 다르면 같은 이름의 메소드로 정의할 수 있다.

한 클래스 내의 같은 이름의 메소드를 여러 개 정의하는 것메소드 오버로딩(method overloading)’ 또는 오버로딩(overloading)’이라고 한다.

 

오버로딩의 조건

1.     메소드 이름이 같아야 한다.

2.     매개변수의 개수 또는 타입이 달라야 한다.

o  메소드 이름이 같더라도 매개변수가 다르면 구별이 되기에 오버로딩이 가능한 것이다. 오버로딩 시 위의 조건을 만족시키지 못하는 메소드는 중복 정의로 간주되어 컴파일 시 에러가 발생한다.

o  오버로딩은 매개 변수로만 구분이 되기에 반환 타입은 오버로딩 구현 시 아무런 영향을 주지 못한다.

 

오버로딩의 예


// 에러, 매개 변수 이름은 다르나 타입이 같이에 오버로딩 성립 X
int add(int a, int b) {return a+b;}
int add(int x, int y) {return x+y;}
 
 
// 반환 타입이 다르나 매개 변수 타입이 같기에 오버로딩 성립 X
int add (int a, int b) {return a+b;}
long add (int a, int b) {return (long(a+b);)}

// 모두 같은 매개변수 타입이지만 순서가 다르므로 오버로딩 O 
long add(int a, long b) {return a+b;}
long add(long a, int b) {return a+b;}

o  같은 일을 하지만 매개변수를 다르게 해야 하는 경우에, 이름은 같고 매개변수를 다르게 하여 오버로딩을 구현한다.

 

오버로딩의 장점

o  오버로딩이 없는 경우 같은 기능을 하는 메소드지만 서로 다른 이름을 가져야 하기 때문에 이름을 짓기도 어렵고 이름들을 일일이 구분해서 기억하기도 어렵다. 하지만 오버로딩을 통해 메소드를 하나의 이름으로 정의하면 기억하기도 쉽고 이름도 짧게 지을 수 있어서 오류 가능성을 줄일 수 있다. 그렇기에 메소드 이름만 보고도 어떤 기능일지 쉽게 예측할 수도 있다.

o  메서드 이름을 짓는데 고민들 덜 수 있고 메소드의 이름을 절약할 수 있다.

 

가변인자(varargs)와 오버로딩

o  JDK 1.5부터 매개변수를 동적으로 지정해 줄 수 있는 기능을 가변인자(variable arguments)’라고 한다. 가변인자는 타입명수명 형식으로 선언하며 printf()가 대표적인 예이다.

public PrintStream printf(String format, Object... args) { }

 

public PrintStream printf(Object... args, String format) { } // 가변인자는 마지막에 선언

-       가변 인자는 마지막에 선언해야 한다. 가변인자인지 아닌지 구별할 방법이 없기에 허용하지 않으며 컴파일 에러가 발생한다.

 

o  매개변수 변수가 다른 메소드를 작성할 때 가변인자를 사용하여 메소드 하나로 대처할 수 있다. 메소드 호출 시 인자 개수를 가변적으로 할 수 있으며 인자가 없는 것부터 배열도 가능하다.

String concatenate(String s1) {...}
String concatenate(String s1, String s2) {...}
String concatenate(String s1, String s2, String s3) {...}
    
static String concatenate(String... s1) {return "s";}

-       매개 변수 개수가 다른 메소드 오버로딩 시 가변인자를 이용하여 메소드 하나도 작성할 수 있다.

 

System.out.println(concatenate());
System.out.println(concatenate("a","b"));
System.out.println(concatenate(new String[] {"A","B"}));

-       인자가 없거나 배열인 경우도 사용 가능하다.

 

o  가변인자는 내부적으로 배열을 이용하기에 선언된 메소드마다 배열이 새로 생성된다. 가변인자가 편리하지만 이 같은 비효율이 있기에 꼭 필요한 경우에만 사용하도록 한다.

o  가변인자를 선언한 메소드를 오버로딩 할 경우 메소드 호출 시 구별되지 못하는 경우가 발생(컴파일 에러)하기 쉽기에 주의해야한다. 가능하면 가변인자를 사용한 메소드는 오버로딩하지 않는 것이 좋다.

o  아래 예제를 보면 오버로딩 된 static String concatenate(String...args) 의 경우 주석을 해제하면 호출 시 어느 메소드로 처리할지 구분이 되지 않아 에러가 발생한다.

package JavaProject;
 
public class Test {
    public static void main(String[] args) {
        String[] strArr = {"100","200","300"};
        
        System.out.println(concatenate("""100","200","300"));// 주석 해제 시 에러
        System.out.println(concatenate("-", strArr));
        System.out.println(concatenate(","new String[] {"1","2","3"}));
        System.out.println("["+concatenate(","new String[0])+"]");
        System.out.println("["+concatenate(",")+"]");// 주석 해제 시 에러
    }
    
    static String concatenate(String delim, String...args) {
        String result = "";
        
        for(String str : args) {
            result+=str + delim;
        }
        return result;
    }
    
/*  주석 해제 시 컴파일 에러
    static String concatenate(String...args) {
        return concatenate("", args);
    }
*/