오버로딩과 오버라이딩의 차이는 JAVA 면접에서, 흔히 나올 수 있는 질문입니다. 이 중에 오늘은 오버로딩 (overloading)에 대해서 간단하게 알아보도록 하겠습니다. 여기에서 언급되지 않은 내용들은, 심화 편에서 이야기를 해 보도록 하겠습니다. 먼저, overload는, 클래스 내에서, 같은 메소드를 여러 개 선언하는 것을 의미합니다.

 

 예를 들어, ArrayList 클래스를 봅시다.

 

 

 List에 넣을 item 하나를 받는 add 메서드가 있습니다.

 

 

그리고 특정한 위치와, List를 넣을 item을 받는 add 메서드가 있어요. 분명한 것은 이 두 메서드의 이름은 add로 같았다는 것입니다.

 

 


 오버로딩을 언제 쓰면 좋을까요? 부터 생각해 봅시다. ArrayList의 맨 뒤에 item을 추가하는 기능. 그리고 특정한 위치에 item을 추가하는 기능을 생각해 볼 수 있습니다.

 

 

 이렇게 구현할 수도 있습니다. 그런데, 이 둘은 arrayList에 add를 한다는 것이 동일합니다. 그러면, 아예 이렇게 하면 어떨까요?

 

 

 조금 더 깔끔해 보입니다. 오버로딩의 목적은 이게 다입니다. 여기서 조금 더 생각을 잘 해 본다면, 이런 패턴도 생각할 수 있습니다. add(item)이 뒤에다가 추가가 되는 것이니, add를 호출했을 때, 내부적으로 add(size, item)을 호출하면 어떨까? size번째 요소에 item을 추가하는 것입니다.

 

 

 이런 식으로 설계를 하는 패턴도 나쁘지 않을 거에요. 이런 패턴은 Scanner의 nextInt 메서드를 보시면 됩니다. 여기서 잠깐. 그런데, 왜 하필 add_front와 같은 것은 고려를 안 했을까요? 저는 설계자가 아니기 때문에 정확하게 잘 모릅니다. 다만, 한 가지 유추를 해 볼 수 있는 것은, c++의 vector 클래스를 생각해 보신다면 push_back의 사용 빈도는 상당히 높습니다. ps를 하시면서 한 문제를 풀 때 많게는 수십번을 쓸 정도로요.

 

 

 이는, item을 넣을 공간이 충분하다면, 상수 시간만에 수행을 할 수 있기 때문입니다. 인덱스 접근하는데 상수 시간, 넣는 시간도 상수.

 

 그렇지 않다고 하더라도, amortized 상수 시간이 보장되고요. 잘 생각해보면, 순서가 중요하지 않는 경우에. 더 정확히 말하면 중간 위치에서 삽입, 삭제가 일어나지 않을 때. 그러면, 배열 기반 자료구조를 이용하는 게 속 편합니다. 그러면 제일 먼저 고려하는 메소드 중 하나는, push_back입니다. 뒤에 추가되는 것은 아무런 부담이 없기 때문입니다. 인접 리스트를 구축할 때를 보면, 어떠한 노드와 연결된 노드가 {1,4,2,3} 순으로 들어가도, {4,1,3,2}로 들어가도 상관 없어요. 그렇기에, 뒤에 추가하는 쿼리만 고려하는 듯 싶어요.

 

 또 다른 예를 보겠습니다.

 

 


 Scanner 클래스를 보겠습니다. nextXXX 메서드가 많이 있다는 것을 알 수 있어요.

 

 

 nextInt는 인자가 없고 리턴 값이 int인 것이 있습니다. 같은 이름, 그렇지만 다른 인자를 받는 메서드를 호출하고 있어요.

 

 

 그리고 인자 하나가 있고, 리턴값이 int인 것이 있어요. 사실, 이들도 오버로딩을 하면 더 깔끔할 겁니다. 왜냐하면, int형 하나를 받는다는 기능 자체는 중복되기 때문입니다. 단지 다른 것은 진법이 명시되었느냐, 그렇지 않느냐. 이 차이일 뿐입니다.

 

 

 오버로딩을 하지 않았다면, 어떻게 되었을지 상상이 잘 안 갑니다. radix를 인자로 받던, 그렇지 않던, int 하나를 받는다는 기능 자체는 동일하기 때문에, 메서드 이름을 둘 다 nextInt로 합니다. 그리고, default인 경우는 10진법이니, 아예 nextInt()를 호출했을 때, 내부적으로, default_radix를 넘겨주는 nextXXX를 호출하면 될 거에요. 대략적으로 이런 패턴이에요.

 

 

 이 둘은, ArrayList의 2개의 add 메서드와 마찬가지로 넘겨주는 인자의 순서 , 개수, type 중 최소한 하나 이상이 다릅니다. signature가 다르다고 합니다. 그런데 nextShort를 봅시다.

 

 

 public int nextInt()하고 비교를 해 봅시다. 인자의 순서, 갯수, type. 셋 다 모두 같습니다. 단지 리턴값만 다를 뿐입니다. 즉, 메서드 short nextShort()와 int nextInt()는 signature가 같습니다. 시그니쳐가 같은 두 메서드는 같은 이름으로 선언할 수 없습니다. 예를 들어, 아래 코드는 컴파일 오류가 납니다.

 

 

 왜 그럴까요?

 

 

 17번째 줄의 m.f(); 를 봅시다. 어느 메서드를 선택해야 하나요? int를 리턴하는 f? 아니면 double을 리턴하는 f? 어느 것을 선택해도 이상하지 않은 상황이 됩니다. 이를 모호하다고 이야기 합니다. 그렇기 때문에 오버로딩을 하려면, 매개 변수의 타입, 갯수, 순서 중 하나 이상이 달라야 합니다.