메서드도 변수와 마찬가지로 같은 클래스 내에서 서로 구별될 수 있어야 하기 때문에 각기 다른 이름을 가져야 한다. 그러나 자바에서는 한클래스 내에 이미 사용하려는 이름과 같은 이름을 가진 메서드가 있더라도 매개변수의 개수 또는 타입이 다르면, 같은 이름을 사용해서 메서드를 정의할 수 있는데, 이것을 우리는 오버로딩이라고 한다. 오버로딩을 지금부터 좀더 자세히 알아보자.
오버로딩 개념
오버로딩은 메서드 오버로딩이라고도 부르며, 한 클래스 내에 같은 이름의 메서드를 여러 개 정의하는 것을 말한다. 오버로딩의 사전적 의미는 '과적하다' 즉, 많이 싣는 것을 의미한다. 보통 하나의 메서드 이름에 하나의 기능만을 구현해야하는데, 하나의 메서드 이름으로 여러 기능을 구현하기 때문에 붙여진 이름이라 생각할 수 있다.
오버로딩의 조건
같은 이름의 메서드를 정의한다고 해서 무조건 오버로딩인 것은 아니다. 오버로딩이 성립하기 위해서는 다음과 같은 조건을 만족해야한다.
- 메서드 이름이 같아야 한다.
- 매개변수의 개수 또는 타입이 달라야 한다.
메서드의 이름이 같아도 매개변수가 다르면 서로 구별될 수 있기 때문에 오버로딩이 가능하다. 위의 조건을 만족시키지 못하는 메서드는 중복 정의로 간주되어 컴파일 시에 에러가 발생한다. 그리고 오버로딩된 메서드들은 매개변수에 의해서만 구별될 수 있으므로 반환 타입은 오버로딩을 구현하는데 아무런 영향을 주지 못한다는 것에 주의해야한다.
오버로딩의 장점
- 오류의 가능성 최소화
하나의 이름으로 정의되기 때문에 메서드명을 기억하기도 쉽고 이름도 짧게 할 수 있어 오류의 가능성을 많이 줄일 수 있다.
- 메서드의 기능 예측이 쉬움
메서드가 여러개여도 오버로딩을 통해 같은 메서드명을 여러개 구현해놓으면 해당 메서드가 어떠한 기능을 하는 메서드인지 쉽게 파악이 가능하다.
- 메서드의 이름 절약
메서드명을 결정하는데 고민을 덜 수 있는것과 동시에 사용되었어야할 메서드명을 다른 메서드의 이름으로 사용할 수 있다.
오버로딩 사용법
예제코드를 통해 오버로딩의 올바론 사용법을 알아보자. 예제 코드는 4개를 준비하였고 내용은 다음과 같다.
예제 1
// 올바르지 않은 오버로딩
int add(int a, int b) {
return a + b;
}
int add(int x, int y) {
return x + y;
}
예제 1은 매개변수의 이름만 다를 뿐 매개변수의 타입이 같기 때문에 오버로딩이 성립하지 않는다. 매개변수의 이름이 다르면 메서드 내에서 사용되는 변수의 이름이 달라질 뿐, 아무런 의미가 없다.
그래서 이 두 메서드는 정확히 같은 것이다.
예제 2
// 올바르지 않은 오버로딩
int add(int a, int b) {
return a + b;
}
long add(int a, int b) {
return (long)(a + b);
}
예제 2는 리턴타입만 다른 경우이다. 매개변수의 타입과 개수가 일치하기 때문에 add(3, 3)과 같이 호출하였을 때 어떤 메서드가 호출된 것인지 결정할 수 없기 때문에 오버로딩으로 간주되지 않는다.
예제 3
// 올바른 오버로딩
long add(int a, long b) {
return a + b;
}
long add(long a, int b) {
return a + b;
}
예제 3은 각 메서드에 int형과 long 매개변수가 하나씩 선언되어 있긴 하지만, 순서가 다른 경우이다. 이 경우 호출 시 매개변수의 값에 의해 호출될 메서드가 구분될 수 있으므로 중복된 메서드 정의가 아닌, 오버로딩으로 간주한다.
예제 4
// 올바른 오버로딩
int add(int a, int b) {
return a + b;
}
long add(long a, long b) {
return a + b;
}
long add(int[] a) {
long result = 0;
for(int i = 0; i < a.length; i++) {
result += a[i];
}
return result;
}
예제 4는 정의된 매개변수가 서로 다르지만, 세 메서드 모두 매개변수로 넘겨받은 값을 더해서 그 결과를 돌려준다. 같은 일을 하지만 매개변수를 달리해야하는 경우에, 이와 같은 이름은 같고 매개변수를 다르게 하여 오버로딩을 구현한다.
가변인자(varargs)와 오버로딩
추가적으로 오버로딩은 가변인자와 엮어 알아야할 것이 있다. 그전에 가변인자에 대해 잠깐 짚고가자.
메서드는 기존에 매개변수 개수가 고정적이었으나, JDK1.5부터는 동적으로 지정해 줄 수 있게 되었으며, 이 기능을 '가변인자' 라고 한다. 사용법과 예제는 다음과 같다.
// 사용법
타입... 변수명
// 예제
public PrintStream printf(String a, Object... b) {
...
}
가변인자는 편리한 대신 한가지 규칙을 지켜주어야 한다. 만약 메서드의 인자가 하나인 경우는 상관없지만, 2개 이상일 때 가변인자를 사용한다면 가변인자는 가장 마지막 인자로 작성해주어야한다. 그렇지 않으면 가변인자인지 아닌지 컴파일러가 구분할 방법이 없어 컴파일 에러가 발생하기 때문이다.
가변인자는 이정도만 짚어보고, 오버로딩과 엮어 주의할점 하나만 알고가보자.
여러 문자 데이터를 하이픈으로 연결하는 메서드가 있다고 가정하자. 예제 코드는 아래와 같다.
class CodeRunner{
public static void main(String[] args){
System.out.println(concatenate("-", "100", "200", "300"));
}
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);
}
}
이 두 메서드는 별 문제가 없어 보이지만 실행해보면 두 오버로딩된 메서드가 구분되지 않아 컴파일 에러가 발생한다. 가변인자를 선언한 메서드를 오버로딩하면, 메서드를 호출했을 때 이와 같이 구별되지 못하는 경우가 쉽게 발생하기 때문에 주의해야한다.
가능하면 가변인자를 사용한 메서드는 오버로딩하지 않는 것이 좋다.
읽어주셔서 감사합니다. 😊
Reference
자바의 정석 - 남궁성
'JAVA' 카테고리의 다른 글
JAVA / 변수의 초기화 (0) | 2020.04.03 |
---|---|
JAVA / 생성자(Constructor) (0) | 2020.04.03 |
JAVA / 메서드(method) (0) | 2020.04.03 |
JAVA / 클래스와 객체 (0) | 2020.04.03 |
JAVA / 배열 (0) | 2020.03.31 |