이론 정리/java

java 오버로딩(overloading)과 오버라이딩(overriding)

철매존 2023. 1. 13. 01:00
728x90

오버로딩, 오버라이딩

오버로딩(Overloading)

메소드 이름이 같지만, 매개변수에 따라 다른 것으로 판단

한번 예를 들어보겠다.

오버로딩 사용

먼저 다음과 같이 메서드를 정의해 준다.

class OverloadingMethods {
    public void ryoochan(Integer iq){
        System.out.println("류찬의 아이큐는 " + iq + " 입니다.");
    }

    public void ryoochan(String look){
        System.out.println("류찬의 외모는 " + look + " 입니다.");
    }
}

보다시피 ryoochan은 같은 이름을 가진 메서드인데, 매개변수가 Integer, String으로 각각 다르게 설정되어 있다.

public void 오버로딩테스트() {
    OverloadingMethods overloadingMethods = new OverloadingMethods();
    int iq = 200;
    String look = "진짜 잘생긴편";

    overloadingMethods.ryoochan(iq);
    overloadingMethods.ryoochan(look);
}

실제로 이를 한번 동작시키면

이렇게 나온다.
둘다 같은 메서드를 사용했지만, 어떤 매개변수를 넣냐에 따라 다른 동작을 하게 된다.

오버로딩 주의점

그럼 이런 경우는 어떨까??

class OverloadingMethods {
    public void ryoochan(Integer iq){
        System.out.println("류찬의 아이큐는 " + iq + " 입니다.");
    }

    public void ryoochan(int bq){
        System.out.println("류찬의 bq는 " + bq + " 입니다.");
    }

    public void ryoochan(String look){
        System.out.println("류찬의 외모는 " + look + " 입니다.");
    }
}

위에서는 Integer를 매개변수로 하는애가 있는데, 이번에는 int를 매개변수로 받는 애를 추가시켰다.

public void 오버로딩테스트() {
    OverloadingMethods overloadingMethods = new OverloadingMethods();
    int iq = 200;
    String look = "진짜 잘생긴편";

    overloadingMethods.ryoochan(iq);
    overloadingMethods.ryoochan(look);
}

다시 동작시키면

이렇게 나온다.

분명 처음과 같은 동작인데, 함수가 추가되어서 다른 메서드가 실행되었다.

Integer와 int처럼 사용 내용은 같지만, 타입이 다른 경우가 있기 때문에 개발을 할 때에 혹시라도 코드가 꼬일때를 대비하여 꼭!! 매개변수를 그냥 넣지 말고 따로 선언해서 넣어주자!

그래서 이거 왜쓰는데?

저 코드의 용례를 보면 파악 가능할 것이다.
각각의 메서드들은 다른 매개변수를 받아서 다른 동작을 하지만, 사실은 ryoochan이라는 사람에 관련된 역할을 수행한다.
그렇기 때문에 쓸데없이 메서드를 나누지 않고, 그냥 하나로 사용해서 메서드 이름 낭비를 없애고 알아보기 쉽게 하는 것이다.(근데 주변 개발자들과 이야기를 나누었을 때에는 오히려 이것때문에 더 헷갈리는 사람도 있다고 한다...)

정리하면

  • Overloading은 하나의 메서드 이름을 가지고, 다른 타입의 매개변수를 통해 다른 메서드로 동작하도록 하는 것이다.
  • 참조/기본 타입의 경우 알아서 구분해 주지만 더 적정할게 있으면 알아서 찾아간다.
  • 이름 낭비를 없애고 코드 역할 확인이 용이하다는 장점이 있다.
  • return은 달라도 매개변수가 같으면 에러가 난다.
    • 이거는 당연한게 매개변수가 들어갈때 똑같으면 java에서 어디를 찾아가야할지 모른다...

Overriding

부모 클래스의 메서드를 자식에서 재정의해서 사용

말 그대로 이미 만들어진 메서드를 자식쪽에서 용도에 맞추어 다시 정의해서 쓰는 것이다.

한번 예를 들어보겠다.

오버라이딩 사용

class Person {
    void look (String input) {
        System.out.println("이 사람은 " + input + "입니다.");
    }
}

class Ryoochan extends Person {
    @Override
    protected void look(String input){
        System.out.println("류찬은 " + input + " 입니다. 이건 팩트입니다.");
    }
}

class Hong extends Person {
    @Override
    protected void look(String input){
        System.out.println("홍길동은 " + input + " 이 아닙니다... 거짓말을 한 것입니다.");
    }
}

다음과 같이 정의해 준다.

여기서 보면 Person이라는 부모 클래스와 여기서서의 내부 메서드 look이 있고, RyoochanHong이 이를 상속받아 재정의 해주었다.

참고로 Override annotation은 확인용으로, 재정의된 코드에 논리적 문제가 없는지를 판단해준다.
즉 저거 없어도 되긴함ㅇㅇ -> 근데 저걸 적어주면 문제를 확인해주기도 하고, 부모 메서드를 상속받아 변경했다는 것을 명시적으로 알 수 있다는 장점이 있으므로 그냥 무조건 쓰도록 하자.

public void 오버라이딩테스트() {
    Person person = new Person();
    Ryoochan ryoochan = new Ryoochan();
    Hong hong = new Hong();

    String lookIs = "존잘";

    person.look(lookIs);
    ryoochan.look(lookIs);
    hong.look(lookIs);
}

이제 한번 테스트를 해주겠다.

이렇게 나온다.
내용을 보면

  • 본래 Person에서의 메서드는 그대로 동작
  • Ryoochan, Hong의 메서드는 재정의한 방식으로 동작

하게 된다.
그리고 당연하지만, 매개변수나 return이 달라져서는 안된다.
부모에서 쓰이는 애를 재정의한 것이기 때문이다.

그래서 이거 왜쓰는데?

이번에도 코드의 용례를 통해 확인 가능하다.
본래 Person(부모)에서의 look은 이 사람의 외모를 보여주는 역할을 했다.
그런데 Ryoochan(자식1)은 칭찬이 들어왔을때 그것이 팩트이지만, Hong(자식2)은 칭찬이 들어오면 당연히 거짓말일 것이다.

따라서,

  • 누군가에 대한 외모의 칭찬이 들어오면
    • Ryoochan이라는 Person은 당연히 팩트일 것이다.
    • Hong이라는 Person은 당연히 거짓말일 것이다.

이렇게 본래 부모에서의 사용 메서드를 들고와서 쓰지만 자식의 상태에 따라 다른 동작이 필요할 때가 있다.
이를 위해 Override를 통해 메서드를 재정의해서 쓰면 된다.
-> 그리고 이 때에 사용법은 부모의 그것에서 크게 변화하지 않도록 하자.