Java

overloading

계산기 예제로 돌아가보자. 우리의 계산기는 2개의 값(left, right)에 대한 연산(sum, avg) 만을 수행 할 수 있다. 그런데 만약 3개의 값을 대상으로 연산을 해야 한다면 어떻게 해야할까? 우선 아래와 같이 입력값을 3개 받아야 할 것이다. 

c1.setOprands(10, 20, 30);

이를 위해서 기존의 setOprands 메소드를 아래와 같은 모습을 수정한다면 2개의 입력값을 받을 수 없게 될 것이다.

public void setOprands(int left, int right, int third){
    this.left = left;
    this.right = right;
    this.third = third;
}

이런 경우 아래와 같이 메소드의 이름을 변경하면 될 것이다.

c1.setOprands2(10, 20);
c1.setOprands3(10, 20, 30);

이것도 좋은 방법이지만 매개변수의 수에 따라서 메소드의 이름이 달라지는 것은 왠지 깔끔한 방법이 아닌 것 같다. 그럼 어떻게 해야 좋을까? 코드를 보자.

package org.opentutorials.javatutorials.overloading.example1;

class Calculator{
    int left, right;
    int third = 0;
     
    public void setOprands(int left, int right){
        System.out.println("setOprands(int left, int right)");
        this.left = left;
        this.right = right;
    }
    
    public void setOprands(int left, int right, int third){
        System.out.println("setOprands(int left, int right, int third)");
    	this.left = left;
        this.right = right;
        this.third = third;
    }
    
    public void sum(){
        System.out.println(this.left+this.right+this.third);
    }
     
    public void avg(){
        System.out.println((this.left+this.right+this.third)/3);
    }
}
 
public class CalculatorDemo {
     
    public static void main(String[] args) {
         
        Calculator c1 = new Calculator();
        c1.setOprands(10, 20);
        c1.sum();       
        c1.avg();
        c1.setOprands(10, 20, 30);
        c1.sum();       
        c1.avg();
        
    }
 
}

아래는 기본 예제와의 차이점이다.

실행 결과는 아래와 같다.

setOprands(int left, int right)
30
15
setOprands(int left, int right, int third)
60
30

아래 코드를 보자.

c1.setOprands(10,20); 

이 코드의 실행 결과는 화면에 아래와 같은 메시지를 출력한다.

setOprands(int left, int right)

다음 코드를 보자.

c1.setOprands(10, 20, 30);

실행 결과는 아래와 같다.

setOprands(int left, int right, int third)

이를 통해서 알 수 있는 것은 매개변수의 숫자에 따라서 같은 이름의, 서로 다른 메소드를 호출하고 있다는 것을 알 수 있다.

이름은 같지만 시그니처는 다른 메소드를 중복으로 선언 할 수 있는 방법을 메소드 오버로딩(overloading)이라고 한다.

오버로딩의 규칙

결론적으로 말하면 메소드 오버로딩은 매개변수를 사용한다. 즉 매개변수가 다르면 이름이 같아도 서로 다른 메소드가 되는 것이다. 반면에 매개변수는 같지만 리턴타입이 다르면 오류가 발생한다. 아래의 코드를 보자.

package org.opentutorials.javatutorials.overloading.example1;
public class OverloadingDemo {
    void A (){System.out.println("void A()");}
	void A (int arg1){System.out.println("void A (int arg1)");}
	void A (String arg1){System.out.println("void A (String arg1)");}
	//int A (){System.out.println("void A()");}
	public static void main(String[] args) {
		OverloadingDemo od = new OverloadingDemo();
		od.A();
		od.A(1);
		od.A("coding everybody");
	}
}

3행과 4행의 메소드 A는 매개변수의 숫자가 다르다. 4행과 5행의 메소드 A는 인자의 숫자는 같지만 매개변수의 데이터 타입이 다르다. 이런 경우는 오버로딩이 가능하다. 메소드를 호출 할 때 전달되는 인자의 데이터 타입에 따라서 어떤 메소드를 호출할지를 자바가 판단 할 수 있기 때문이다. 하지만 메소드의 반환값은 메소드를 호출하는 시점에서 전달되지 않는 정보이기 때문에 오버로딩의 대상이 될 수 없다.

상속과 오버로딩

상속의 관계에서도 오버로딩을 사용할 수 있을까? 물론이다. 

package org.opentutorials.javatutorials.overloading.example1;
public class OverloadingDemo2 extends OverloadingDemo{
    void A (String arg1, String arg2){System.out.println("sub class : void A (String arg1, String arg2)");}
	void A (){System.out.println("sub class : void A ()");}
	public static void main(String[] args) {
		OverloadingDemo2 od = new OverloadingDemo2();
		od.A();
		od.A(1);
		od.A("coding everybody");
		od.A("coding everybody", "coding everybody");
		
	}
}

실행 결과는 아래와 같다.

sub class : void A ()
void A (int arg1)
void A (String arg1)
sub class : void A (String arg1, String arg2)

클래스 OverloadingDemo2는 OverloadingDemo을 상속 받고 있다. OverloadingDemo2의 3행에서 정의된 메소드 A는 문자열을 데이터타입으로 하는 두개의 매개변수를 가지고 있다. 이러한 형태의 변수는 부모 클래스에서는 정의되어 있지 않기 때문에 메소드 오버로딩이 되는 것이다. 반면에 4행에서 정의된 메소드 A는 매개변수가 없다. 그리고 부모 클래스에는 이미 매개변수가 없는 메소드 A가 존재한다. 이 둘은 매개변수의 형태가 같기 때문에 오버로딩이 아니라 오버라이딩에 해당한다.

overriding VS overloading

오버라이딩과 오버로딩은 용어가 참으로 헷갈린다. 당연하다. 중요한 것은 오버라이딩이 무엇이고 오버로딩이 무엇인가를 구분하는 것은 아니다. riding(올라탄다)을 이용해서 부모 클래스의 메소드의 동작방법을 변경하고, loading을 이용해서 같은 이름, 다른 매개변수의 메소드들을 여러개 만들 수 있다는 사실을 아는 것이 중요하다. 다만 학습이나 협업의 과정에서 개념을 주고 받을 때는 용어가 중요해진다. 필자의 생각에 이 개념들이 헷갈리는 이유는 over라는 공통분모 때문이다. over를 제외하고 알아두면 덜 헷갈리지 않을까 싶다. (참고로 overriding는 재정의라는 사전적인 의미가 있습니다.)

보충수업

위의 예제는 overloading을 설명하기 위한 예제일뿐 현실적이지 않다. 더 많은 값을 대상으로 연산을 해야 한다면 어떻게 해야할까? 아래와 같이 코드를 변경해보자.

package org.opentutorials.javatutorials.overloading.example1;

class Calculator{
    int[] oprands;
    
    public void setOprands(int[] oprands){
        this.oprands = oprands;
    }
    
    public void sum(){
        int total = 0;
        for(int value : this.oprands){
        	total += value;
        }
    	System.out.println(total);
    }
     
    public void avg(){
    	int total = 0;
        for(int value : this.oprands){
        	total += value;
        }
    	System.out.println(total/this.oprands.length);
    }
}
public class CalculatorDemo {
    public static void main(String[] args) {
    	Calculator c1 = new Calculator();
        c1.setOprands(new int[]{10,20});
        c1.sum();       
        c1.avg();
        c1.setOprands(new int[]{10,20,30});
        c1.sum();       
        c1.avg();   
    }
}

차이점은 아래와 같다.

위의 코드는 인자로 배열을 사용하고 있다. 이렇게하면 하나의 인자로 여러개의 값을 받을 수 있다.

댓글

댓글 본문
  1. hvii
    20200811
  2. EunSeok Kang
    20200807 잘보고갑니다.
  3. kimtahen
    죄송합니다만, 오버로딩과 관련되어있다는 것이 요지가 아닌, 오버로딩만을 사용하여 코딩하는 것은 현실적이지 않다고 하며 배열을 사용하는 방법을 예시로 든 것입니다.
    대화보기
    • 김요한
      생활코딩 님의 오버로딩 예제를 보고 공부하고 있습니다...

      코드를 봤을 때 이 코드가 오버로딩이랑 무슨 관련이 있는지 잘 모르겠고

      코드 자체도 foreach문으로 되어있는데...

      제가 foreach문을 잘 몰라서

      평범한 배열로 풀어서 다시 작성해봤는데 작동을 안하는데 무슨 차이가 있는지 가르쳐주시면 감사합니다 ㅠ

      <생활코딩 님의 코드>



      class Calculator{
      int[] oprands;

      public void setOprands(int[] oprands){
      this.oprands = oprands;
      }

      public void sum(){
      int total = 0;
      for(int value : this.oprands){
      total += value;
      }
      System.out.println(total);
      }

      public void avg(){
      int total = 0;
      for(int value : this.oprands){
      total += value;
      }
      System.out.println(total/this.oprands.length);
      }
      }
      public class CalculatorDemo {
      public static void main(String[] args) {
      Calculator c1 = new Calculator();
      c1.setOprands(new int[]{10,20});
      c1.sum();
      c1.avg();
      c1.setOprands(new int[]{10,20,30});
      c1.sum();
      c1.avg();
      }
      }


      <foreach문을잘 몰라서 제가 일반 배열로 작성한 코드>







      class Calculator11 {


      int[] oprands;



      public void setoprands(int[] oprands) {
      this.oprands=oprands;

      }



      public void sum() {
      int total=0;

      for(int i=0; i<this.oprands.length; i++) {
      total+=this.oprands[i];



      }System.out.println(total);



      }







      public void avg() {
      int total=0;

      for(int i=0; i<this.oprands.length; i++) {
      total+=this.oprands[i];

      }

      System.out.println(total/this.oprands.length);

      }

      }







      public class overloadingEample2 {


      public static void main() {


      Calculator11 c1=new Calculator11();

      c1.setoprands(new int[] {222,20});

      c1.sum();

      c1.avg();

      c1.setoprands(new int[] {10,20,30});

      c1.sum();

      c1.avg();

      }





      }
    • hide&seek
      코딩의 주제에 관해 중요한 건 아닐 수 있지만 operand 스펠링 항상 신경쓰여요!

      밑에 댓글 다시는 분들도 그대로 따라 쓰는 경우가 있길래 댓들 달게 되었습니다!
    • 김시은
      저도 이 고민을 하고 있었는데 정말 많이 도움이 되었습니다.
      마지막에 적용할때에 if문 사용 대신에, this.arg로 직접 나누어도 좋은 코드가 되는 것 같습니다!!
      대화보기
      • 송승현
        2번째 영상 : JAVA - overroading(2/2)에 8분 48초 설명 오류 있습니다.

        이것은 메소드 오버라이딩이 됩니다. (X) -> 이것은 메소드 오버로딩이 됩니다. (O)
      • 김승민
        2020-04-17
        일하면서 공부 하다보니.. 일주일만에 왔네요;;;
        그래도 끊기지 않게 열심히 가보겠습니다~
      • 흐무
        2020.03.10
        오버로딩 : 메소드의 이름이 동일하지만 데이터타입과 매개변수가 다르다.
        오버라이딩: 상위클래스에서 상속받아 메소드를 재정의해서 사용한다. 리턴타입이 같아야한다.
      • 문바이
        OverRiding : 상위 class-method 를 재정의 Redefine한다.
        OverLoading : 기본적으로 class-method는 1개씩만 정의하 가능한데 과적하듯 추가해서 다양한 input type을 지정한다. 단 return type은 변경할 수 없다.
        (return type을 여러개로 정의하면, 이를 가져다 사용하는 측에서 많은 예상치 못한 오류가 발생할가능성이있음)
        대화보기
        • aminora
          오버라이딩 vs 오버로딩
          오버라이딩(riding : 올라탄다) => 부모클래스에서 상속받은 메서드 동작방법을 변경
          오버로딩(loading: 불러낸다) => 같은이름이지만 다른 매개변수를 받고 다른 결과를 내는 메서드들을 여러개 만들수 있다.
        • 2020 01 30 1236
          오버로딩 (1/2) 까지 학습.
        • 워나
          2019/10/17 완료
        • 허공
          감사합니다!
        • PassionOfStudy
          191003(목) - (2)
          수강완료~
        • 김진철
          190924 일단 듣자
        • 홍주호
          20190912 완료
        • 다나가
          190903 - 수강완료
        • doevery
          수강완료
        • 지미츄
          감사합니다
        • 초보
          써드만 왜 초기화값을 0 으로 정한건가요??
          int left, right;
          int third = 0;
          이것과
          int left, right, third;
          이것의 차이점이 무엇인가요??
        • 123ad
          맞아요... 결과랑 코드가 다르네용..
          대화보기
          • 7월 15일 시작
            --- 오늘은 여기까지 하겠습니다 ---
          • 얼그레이
            감사합니다.
          • John Johnson
            말씀하신 대로 입력값이 2개일 때는 2로 나누는게 말이 됩니다. 각각의 Constructor에서 divisor를 선언해 주는 방법을 써 해결 할 수 있습니다.
            대화보기
            • pacuws
              궁금한 점이 생겨 질문드립니다.

              setOprands 의 인자가 2개일 때 3번째 숫자가 더해지는걸 방지하기 위해 int thrid 의 값을 0으로 설정해둔것은 알겠습니다. 다만 sum() 과 달리 avg() 메소드는 setOprands 의 인자 값들과 상관 없이 항상 3으로 나누고 있습니다.
              코드를 복사해서 이클립스에서 실행해 보았지만 역시나 2개의 인자 값을 넣은 경우도 평균을 /3 하고 있습니다.

              본문의 실행결과와 코드를 복사하여 실행한 결과가 다른데 다른분들은 이해 가시나요?
            • 6/17시작
              1독을 빨리 하고 천천히 다시 봐야겠습니다.

              6/28 완료
            • 라또마니
              머리에 넣을 수 있는 저장장치가 오버 됐어요! 오늘은 여기까지...
            • LuiGee
              저 댓글 달았던 당시 최신 버전을 사용했었습니다. 제가 알기로는 third는 여기서 지역 변수가 아니라 인스턴스 변수라 따로 할당하지 않아도 초기값(0)을 가집니다. 시간이 조금 지나서 정확하게 기억은 하지 못하겠네요.
              대화보기
              • j-graphy
                2019. 2. 19. 학습완료
              • j-graphy
                혹시 자바 어떤 버전을 사용하고 계신가요?
                int left, right, third;
                와 같이 선언만 해주고, 초기화를 해주지 않았을 때
                자바에서 int라는 데이터 타입에 대해서 0이라는 값을 기본으로 할당하는 것이 맞나요?
                변수 선언 후에 초기화하지 않으면 버그가 발생할텐데요.
                대화보기
                • 호두
                  고맙습니다
                • ㅋㅌㅍㅊ
                  보충수업에 나와있는 내용으로 오버라이딩이 안되요
                  class Calculator{
                  int[] oprands;
                  int total;

                  public void setOprands(int[] oprands){
                  this.oprands = oprands;
                  }

                  public void sum(){
                  int total = 0;
                  for(int value : this.oprands){
                  total += value;
                  }
                  System.out.println(total);
                  }

                  public void avg(){
                  int total = 0;
                  for(int value : this.oprands){
                  total += value;
                  }
                  System.out.println(total/this.oprands.length);
                  }
                  }
                  class CalculatorParent extends Calculator{
                  public void sum() {
                  System.out.println("입니다");
                  }
                  }
                  public class dadsd {
                  public static void main(String[] args) {
                  Calculator c1 = new Calculator();
                  c1.setOprands(new int[]{10,20});
                  c1.sum();
                  c1.avg();
                  c1.setOprands(new int[]{10,20,30});
                  c1.sum();
                  c1.avg();
                  }
                  }
                • LuiGee
                  sum과 avg 메소드를 보시면 third값을 포함해서 계산하도록 바뀌었습니다. setOprands 메소드가 매개변수를 2개를 받든 3개를 받든 계산이 제대로 되기 위해서 일부러 third의 값을 0으로 지정하신 것으로 생각합니다.

                  그런데 이 질문에 대답하기 위해 검색하고 코드를 분석하다보니 몇 가지를 알게 되었습니다.

                  1. 사실 말씀하신 대로 int left, right, third;로 선언하셔도 똑같이 작동합니다. Java에서는 int에 별다른 값을 지정해주지 않으면 일단 0이라는 값을 부여하기 때문입니다.

                  2. 예제에서는 setOprands(10, 20)을 먼저 사용하고 setOprands(10, 20, 30)을 그 다음에 사용합니다. 이 경우에는 문제 없이 작동하지만 이 둘의 순서를 바꾸면 문제가 발생합니다. 바로 setOprands(10, 20)을 해도 여전히 값이 setOprands(10, 20, 30)을 했을 때와 똑같다는 것입니다. (int left, right, third; 선언도 마찬가지입니다.)

                  이 이유는 third 값에 setOprands(10,20,30)을 통해 30이 할당되고 초기화가 되지 않기 때문입니다. 즉 원래 의도였던 third의 초기화가 생각대로 작동하지 않는 것 같습니다. 이를 위해

                  public void setOprands(int left, int right) {
                  System.out.println("setOprands(int left, int right)");
                  this.left = left;
                  this.right = right;
                  this.third = 0;
                  }

                  이렇게 third에 0을 할당하도록 코드를 추가해주면 순서를 바꿔도 문제 없이 값을 출력합니다. 매개변수를 두개만 받으면 매번 third값을 0으로 수정해주는 것이죠.

                  혹시나 더 깊게 담긴 의도를 모르고 하는 말일 수 있겠지만 이고잉님이 오버로딩 개념을 설명하기 위해 비현실적이고 인위적인 케이스를 보여주시려다가 미처 체크 못하고 넘어가신 부분일 수 있지 않을까 생각합니다.
                  대화보기
                  • 웅이
                    위 첫번째 강의 예제소스코드를 보면
                    class Calculator{
                    int left, right;
                    int third = 0;
                    3,4,5 라인에 이런 코드가 있습니다.
                    입력값을 10,20,30 으로 입력하듯이
                    위 라인에서도 int left, right, third 이렇게 선언 할 수 있을 것 같은데,
                    두 방법이 차이가 있는것인가요?
                    그리고 setOprands의 입력값을 받을 매개변수를 선언하는것을 넘어
                    int left, right와는 다르게 0이라는 값을 할당 하는 이유는 뭔가요?
                    나중에 다른값을 입력값으로 받으면 그냥 덮어쓰기가 되는부분이라 상관없는건가요?
                  • ShinHi
                    public class CalculatorDemo {

                    public static void main(String[] args) {

                    Calculator c1 = new Calculator();
                    c1.setOprands(10, 20);
                    c1.sum();
                    c1.avg();
                    //System.out.println(good);
                    c1.setOprands(10, 20, 0);
                    c1.sum();
                    c1.avg();

                    }

                    }

                    여기서 혹시

                    public class CalculatorDemo {

                    public static void main(String[] args) {

                    Calculator c1 = new Calculator();
                    c1.setOprands(10, 20);
                    c1.sum();
                    c1.avg();
                    //System.out.println(good);
                    c1.setOprands(10, 20, 0);
                    c1.sum();
                    c1.avg();
                    c1.setOprands(30, 40);
                    c1.sum();
                    c1.avg();

                    }

                    }

                    처럼

                    c1.setOprands(30, 40);
                    c1.sum();
                    c1.avg();

                    이 코드가 한 번 더 필요할 경우 String good의 변수값이

                    "three" 에서 "" 값으로 변환되는 코드가 없기 때문에

                    public void setOprands(int left, int right){
                    System.out.println("setOprands(int left, int right)");
                    this.left = left;
                    this.right = right;
                    this.good="";
                    }

                    같은 방법으로 코드를 작성하면 더 나은 방법이 아닐까 생각해봤습니다.
                    대화보기
                    • chang26
                      //강의의 예제에서는 평균값을 구하는 부분에서 허점이 있다. 그래서 조건문을 이용해서 해결!!

                      package org.opentutorials.javatutorials.overloading;

                      class Calculator{
                      int left, right;
                      int third = 0;
                      String good ="";

                      public void setOprands(int left, int right){
                      System.out.println("setOprands(int left, int right)");
                      this.left = left;
                      this.right = right;
                      }

                      public void setOprands(int left, int right, int third){
                      System.out.println("setOprands(int left, int right, int third)");
                      this.left = left;
                      this.right = right;
                      this.third = third;
                      good = "three";
                      }

                      public void sum(){
                      System.out.println(this.left+this.right+this.third);
                      }

                      public void avg(){
                      if(good.equals("")) {
                      System.out.println((this.left+this.right+this.third)/2);
                      }else if(good.equals("three")) {
                      System.out.println((this.left+this.right+this.third)/3);
                      }
                      }
                      }

                      public class CalculatorDemo {

                      public static void main(String[] args) {

                      Calculator c1 = new Calculator();
                      c1.setOprands(10, 20);
                      c1.sum();
                      c1.avg();
                      //System.out.println(good);
                      c1.setOprands(10, 20, 0);
                      c1.sum();
                      c1.avg();

                      }

                      }

                      이렇게 하면 원하시는 결과를 얻으실수 있습니다. 다른분들도 참고해주세요

                      setOprands(int left, int right)
                      30
                      15
                      setOprands(int left, int right, int third)
                      30
                      10
                      대화보기
                      • hi개발자
                        18.10.10 공부완료
                      • for each문과 연산자 논리연산자 복습추천드립니다
                        조건문이 만족할때까지 좌항에 우항을더하는부분입니다
                        대화보기
                        • 잘 보시면 int [] oprands; 는 class Calculator 직속입니다
                          대화보기
                          • 학생01
                            마지막 보충수업부분 정말 새롭네요. 강의내용잘 보고있습니다.
                          • 전민희
                            보충수업은 따로 동영상 수업이 없나요? ㅠㅠ 혼자 하려니 너무 힘드네요
                          • 보충수업을 안보긴했는데 글에서 어느부분을 모르시겠다는 건지 모르겠네요 혹시 for-each문을 모르시는건가요 교육자님이 설명해주셨는데
                            대화보기
                            • 아뇨
                              대화보기
                              • 변수는 어때요
                                3이 상수이기 때문에 재사용할 수 없는 것이니까 3 대신 변수를 넣으면 어떨까요?
                                생성자 내부에 변수를 매개변수 개수만큼의 값으로 초기화 해주면 적당할 것 같습니다.
                                대화보기
                                • 질문드려요
                                  굳이 setoprands 에 this.를 해줘야 하나요?
                                • jsm5272
                                  마지막 보충수업에서
                                  public void sum(){
                                  int total = 0;
                                  for(int value : this.oprands){
                                  total += value;
                                  }
                                  System.out.println(total);
                                  }

                                  이게 어떻게 동작해서

                                  public class CalculatorDemo {
                                  public static void main(String[] args) {
                                  Calculator c1 = new Calculator();
                                  c1.setOprands(new int[]{10,20});
                                  c1.sum();

                                  이거에 해당되는 값이 30되는지 영상이나 글로 설명좀 부탁드리겠습니다.
                                  total +=value; 이게 total = total + value 값인거는 검색을 통해 찾았는데
                                  어떤식으로해서 동작하는지 자세하게 좀 알고싶습니다.
                                • 자바배우고싶어요
                                  자바를 알려주셔서 감사합니다.
                                  오버로딩 공부를 하면서 의문점이 생겼습니다.

                                  매개변수를 하나를 추가하여 sum()함수 재사용성을 위해

                                  public void sum()
                                  {
                                  System.out.println(left + right + third);
                                  }

                                  하는 것은 맞지만 avg()함수의 경우
                                  public void avg()
                                  {
                                  System.out.println((left + right + third) / 3);
                                  }

                                  만일 값을 두개를 넣고 평균을 구하게 되면 3개의 평균값이 나오게 됩니다.
                                  avg() 메소드를 오버로딩으로 매개변수를 구별하기 위해
                                  public void avg(int left, int right)
                                  public void avg(int left, int right, int third)
                                  이렇게 오버로딩을 해도 될까요?
                                • 이태호
                                  7/7
                                  오버로딩이란 같은 매소드 이름과
                                  다른 파라미터의 수 또는 파라미터의 다른 데이터 타입
                                • 멀캠A_Son
                                  완료
                                버전 관리
                                egoing
                                현재 버전
                                선택 버전
                                graphittie 자세히 보기