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. 자바잡아
    22.05.03 오버로딩 / 오버라이딩 완료

    오버로딩 : 부모꺼 끌어와서 사용(메서드 중복 사용 가능 단, 파라미터 값 설정이 달라야함)

    오버라이딩 : 끌어온거 자식이 재정의
  2. 20220426
  3. aesop0207
    220329 Tue.
  4. 생활코딩짱
    public int avg() {
    if(this.third ==0) {
    return ((this.left + this.right) / 2);
    }else if (this.third!=0){
    return ((this.left + this.right + this.third) / 3);
    }
    return 0;

    평균값 이렇게 해야되네요 근데마지막 return 0;이 왜 있어야되는지는 잘 모르겠어요 이클립스가 만들어줬습니다;;
  5. 모찌말랑카우
    22.02.15 완료
  6. aesop0207
    220208 Tue.
    예제 avg() 결과값 이상
  7. 행달
    22.02.05 완료
  8. 드림보이
    2021.12.09. overloading 파트 수강완료
  9. syh712
    2021-12-08

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

    메소드 오버로딩은 매개변수를 사용. 즉 매개변수가 다르면 이름이 같아도 서로 다른 메소드가 됨.
    반면에 매개변수는 같지만 리턴타입이 다르면 오류가 발생.


    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 ()");}

    OverloadingDemo2의 3행에서 정의된 메소드 A는 문자열을 데이터타입으로 하는 두개의 매개변수를 가지고 있다. 이러한 형태의 변수는 부모 클래스에서는 정의되어 있지 않기 때문에 메소드 오버로딩.

    반면에 4행에서 정의된 메소드 A는 매개변수가 없다. 그리고 부모 클래스에는 이미 매개변수가 없는 메소드 A가 존재한다. 이 둘은 매개변수의 형태가 같기 때문에 오버로딩이 아니라 오버라이딩.

    riding(올라탄다)을 이용해서 부모 클래스의 메소드의 동작방법을 변경하고, loading을 이용해서 같은 이름, 다른 매개변수의 메소드들을 여러개 만들 수 있다는 사실을 아는 것이 중요.
  10. 네제가해냈습니다
    211117
  11. 성치
    2021-11-01 완료
  12. 1019
  13. 미NI언
    10.11 완료
  14. devfrank
    apple 라는 예시를 들어보면,

    나는 apple이 pineapple처럼 보여서 앞으로 apple = pineapple로 정의했다.
    (오버라이딩)

    apple 이라 하면 사과가 생각나지만,
    apple 이라는 핸드폰 업체가 생겨 사과, 휴대폰 업체 두가지의 의미를 갖게 되었다.
    상황을 메소드라 생각할때, 먹는상황에서 apple은 사과일것이다.
    하지만 회사의 주가를 생각할떄, 휴대폰업체의 apple은 업체이름일것이다. (오버로딩)
  15. 멋을아는남자
    잘보고갑니다. 감사합니다.
  16. 베이스박
    2021.9.15 학습완료. 감사합니다.
  17. super1Nova
    210823
  18. 악어수장
    2021-05-07 완료
  19. 하연주
    210208 완료
  20. rhkrwogns92
    3개의 매개변수가 있는 경우
    2개의 매개변수만 쓸경우 하나를 0으로 설정을 안해놓으면 원하지 않는 값이 들어 갈 수 있다는 얘기시죠 ??
    이해했습니다!
    친절한 설명 감사합니다ㅎㅎ
    대화보기
    • 김보안
      pakage 이름과 class 이름을 확인해보시고, 복사 붙여넣기 하실때는
      pakage와 class 이름까지 복사하지 마시고 안에 코드부분만 복사하셔서 사용해보세요
      대화보기
      • 김보안
        third를 0으로 초기화 해놓은 이유 설명드리겠습니다.

        변수에 값을 지정해놓지 않으면 일명 쓰레기값이 들어가 원하지 않는 값이 들어갈 수 있습니다.

        그런데, left, right 는 초기화를 해놓지 않고 third만 초기화를 한 이유를 설명드리자면

        매개변수가 2개일때 left, right는 항상 값을 지정해놓고 sum() 계산을 하게됩니다.

        그런데 이번에 매개변수가 3개인 setOperands를 오버로딩 해서 sum() 함수를

        System.out.println(this.left+this.right); 에서

        System.out.println(this.left+this.right+this.third); 로 변경하게 되었습니다.

        여기서 만약, third를 0으로 추가하지 않아 쓰레기값이 들어가고 매개변수 2개짜리의 계산을 하게되면

        left값 + right값 + 쓰레기값 이 sum에서 계산되기 때문에

        매개변수 2개의 sum을 계산하더라도 2개만 더해진 값을 주기위해 third를 0으로 초기화 하신거 같습니다.







        결론 : 매개변수 2개의 sum을 계산할때 쓰레기값이 들어가는것을 방지하기 위해 third를 0으로 초기화했다.
        대화보기
        • 김태현
          공부완료

          메소드는 같을 수 있으나 매개변수가 각각 달라야 한다.
        • 김곰
          파일을 그대로 붙여넣기 해서 보고 있는데 자꾸 에러가 뜨고 x표시를 보면 "rename in file" 또는 'rename in workplace' 라고 뜹니다. 제가 뭘 잘못한걸까요 ㅠㅠ
        • rhkrwogns92
          영상 시청 완료!!

          질문이 있습니다.

          class Calculator{
          int left, right;
          int third = 0;

          여기서 third를 0이라고 선언 하셨는데
          왜 이렇게 하신건가요 ??

          그냥 int left, right, third ;
          이렇게 선언해도 정상 작동 하던데 이유가 따로 있는 건가요 ??
        • hvii
          20200811
        • EunSeok Kang
          20200807 잘보고갑니다.
        • 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: 불러낸다) => 같은이름이지만 다른 매개변수를 받고 다른 결과를 내는 메서드들을 여러개 만들수 있다.
              • ENJOY
                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를 선언해 주는 방법을 써 해결 할 수 있습니다.
                  대화보기
                  버전 관리
                  egoing
                  현재 버전
                  선택 버전
                  graphittie 자세히 보기