java와 객체지향언어2

jungnoeun·2021년 11월 14일
0

java

목록 보기
6/22

오버로딩(overloading)

: 한 클래스내에 같은 이름의 메서드를 여러개 정의하는 것.

  • 메서드 오버로딩(method overloading) 또는 오버로딩(overloading)이라고 한다.
  • 보통 하나의 메서드 이름에는 하나의 기능만을 구현해야하는데, 하나의 메서드 이름으로 여러 기능을 구현한다.



<오버로딩이 성립하기 위한 조건>

  1. 메서드의 이름이 같아야 한다.
  2. 매개변수의 개수 또는 타입이 달라야 한다.

위의 조건을 만족시키지 못하는 메서드는 중복정의로 간주되어 컴파일시 에러가 발생한다. 그리고 오버로딩은 매개변수에 의해서만 구별되므로 반환타입은 오버로딩을 구현하는데 아무런 영향을 주지 못한다.


오버로딩의 예

1) 매개변수의 이름이 다른 경우

int add (int x, int y){}
int add (int a, int b){}

다음과 같이 매개변수의 타입과 개수가 같고 이름만 다른경우, 오버로딩으로 인정되지 않는다. 이를 컴파일시 'add(int,int) is already defined'라는 메시지가 나타날 것이다.


2) 메서드의 리턴타입만 다른 경우

int add (int a, int b) {return a+b;}
int add (int a, int b) [return log(a+b);]

위에서 말했듯이 리턴타입은 오버로딩을 구현하는데 아무런 영향을 주지 못하므로 오버로딩이 성립되지 않는다. 1번과 같은 에러메시지가 발생한다.


3) 다른타입의 매개변수의 순서가 다른경우

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

3번의 경우 매개변수의 값에 의해 호출될 메서드가 구분될 수 있으므로 오버로딩이 성립한다.
이처럼 매개변수의 순서만을 다르게 하면 사용자가 매개변수의 순서를 기록하지 않아도 된다는 장점이 있지만 이는 단점이 될 수도 있다.

add(3,3L)을 호출하면 첫번째 메서드가, add(3L,3)을 호출하면 두번째 메서드가 호출이 된다. 하지만 이 경우 add(3,3)은 호출할 수 없다. 두 메서드중 어느 메서드가 호출될 것인지 알 수 없기 때문이다.




오버로딩의 장점

  1. 여러 메서드들이 하나의 이름으로 정의될 수 있다.
    예를 들어 println()의 경우 오버로딩을 통해 여러 메서드들이 하나의 이름으로 정의될 수 있다. 이는 기억하기 쉽고 이름도 짧게할 수 있어 오류의 가능성이 줄어든다.

  2. 메서드의 이름을 절약할 수 있다.
    하나의 이름으로 여러개의 메서드를 정의할 수 있으므로 이름을 짓는데 고민을 덜 수 있다.





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

가변인자 : 메서드의 매개변수의 개수를 동적으로 지정해줄 수 있게된 기능

  • 선언형식 : 타입...변수명

예시

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

만약 가변인자외에도 매개변수가 더 있으면 가변인자를 매개변수중 제일 마지막에 선언해야 한다. 그렇지 안그러면 가변인자인지 구별할 방법이 없어 컴파일 에러가 발생한다.

//컴파일 에러 발생 - 가변인지는 항상 마지막 매개변수여야한다.
public PrintStream printf(Object... args, String format){}

메서드의 간소화
여러 문자열을 하나로 결합하여 반환하는 concatenate메서드를 작성하면 아래와 같이 매개변수 개수를 다르게 해서 여러개의 메서드를 작성해야 한다.

String concatenate(String s1, String s2) {...}
String concatenate(String s1, String s2,String s3) {...}
String concatenate(String s1, String s2,String s3, String s4) {...}

하지만 가변인자를 사용하면 메서드 하나로 간단히 대체할 수 있다.

String concatenate(String... args)

이 메서드를 호출할땐느 인자의 개수를 가변적으로 할 수 있다. 인자가 없어도 되고 배열도 인자가 될 수 있다.

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

-> 위와 같은 가변인자는 내부적으로 배열을 이용한다. 그래서 가변인자가 선언된 메서드를 호출할 때마다 배열이 새로 생성된다. 가변인자가 편리하지만 비효율적이므로 필요할때만 사용한다.





가변인자와 배열매개변수의 차이

이러한 가변인자는 매개변수의 타입을 배열로 하는 것과 어떤 차이가 있을까?

  • 매개변수의 타입을 배열로 하면, 반드시 인자를 지정해줘야하기 때문에, 아래의 코드에서처럼 인자를 생략할 수 없다. 그래서 null이나 길이가 0인 배열을 인자로 지정해줘야 한다.
String concatenate(String[] str){...}

String result = concatenate(new String[0]);
String result = concatenate(null);
String result = concatenate(); //error발생 -> 인자가 필요함

가변인자 오버로딩시 주의점

static String concatenate(String delim, String... args){
	String result = "";
	for(String str : args){
		result +=str+delim;
	}
}

static String concatenate(String... args){
	return concatenate("",args);
}

-> 이 두 메서드는 별 문제없어보이지만 컴파일하면 컴파일에러가 발생한다. 에러의 이유는 두 오버로딩된 메서드가 구분되지 않아서 발생하는 것임을 알 수 있다. 가변인자를 선언한 메서드를 오버로딩하면, 메서드를 호출했을때 이와 같이 구별되지 못하는 경우가 발생하기 쉽기 때문에 주의해야 한다. 가능하면 가변인자를 사용한 메서드는 오버로딩하지 않는 것이 좋다.

profile
개발자

0개의 댓글