오버로딩(Overloading)과 오버라이딩(Overriding)

    오버로딩

    같은 이름의 메서드를 여러개 정의하는 것  (overload = 과적하다)

     

    오버로딩은 메서드의 매개변수의 개수나 타입을 다르게 정의하여 호출 시점에 어떤 메서드가 호출될지를 결정한다.

     

    Example 1 

    void println()
    void println(boolean x)
    void println(char x)
    void println(char[] x)
    .
    .
    .

     

    오버로딩은 메서드 이름이 같아야 하며, 매개변수의 개수 또는 타입이 달라야한다. 메서드 이름이 같더라도 매개변수의 개수나 타입이 다르지 않다면 컴파일러가 어떤 메서드를 호출해야 하는지 구분할 수 없다.

     

    따라서 매개변수의 타입에 따라서 오버로딩된 메서드들 중 하나가 선택되어 실행된다. 오버로딩을 사용하지 않았더라면 println(), printlnBollean(boolean x) 처럼 모든 메서드에 이름을 지정해주어야 했을 것이다. 따라서 동일한 이름의 메서드가 다양한 기능을 제공하여 코드의 가독성과 유지보수성을 향상시킬 수 있다.

     

    class Test {
        int calculate(int a) { return a + 10; }
        double calculate(int a) { return a + 10.0; } // 컴파일 에러
    }

    오버로딩에서 반환타입은 판단 기준이 되지 않는다. caculate(5)가 호출되면 반환 타입으로만으로는 어떤 메서드를 호출해야 할지 알 수 없기 때문에 컴파일러가 오류를 발생시킨다. 

     

    오버라이딩

    부모 클래스로부터 상속받은 메서드를 자식 클래스에서 재정의 하는 것 

     

    상속받은 자손 클래 자신에 맞게 확장하거나 변경해야하는 경우 오버라이딩할 수 있다. 이때 메서드의 이름, 매개변수, 반환타입이 완전히 같아야 한다. 

     

    부모 클래스의 메서드보다 좁은 범위의 접근제어자로 변경할 수 없다.

    class Parent {
        public void display() {
            System.out.println("Parent display");
        }
    }
    
    class Child extends Parent {
        @Override
        protected void display() { // 오류: 접근 제어자를 더 좁은 범위로 변경
            System.out.println("Child display");
        }
    }
    
    public class Main {
        public static void main(String[] args) {
            Parent obj = new Child();
            obj.display(); // 컴파일 에러
        }
    }

     

     

    부모 클래스를 참조타입으로 사용하게되면 Parent parent = new Child(); parent.display();

    Parent에서는 display() 메서드가 public이지만 Child에서는 protected로 좁아지기 때문에 호출이 불가능하게 된다.

     

    또한, 부모 클래스의 메서드보다 많은 수의 예외를 선언할 수 없는 이유도 비슷한 맥락이다. 

    class Parent {
        public void display() throws IOException {
            System.out.println("Parent display");
        }
    }
    
    class Child extends Parent {
        @Override
        public void display() throws IOException, SQLException { // 컴파일 에러 발생
            System.out.println("Child display");
        }
    }

     

    Parent의 display()는 IOException만 던질 수 있다고 선언하고, Child의 display()는 IOException과 SQLException을 던진다고 선언했다고 가정하자.

     

    Parent obj = new Child(); // 부모 타입 참조로 자식 객체를 참조
    try {
        obj.display(); // 부모 선언에 따르면 IOException만 처리하면 됨
    } catch (IOException e) {
        System.out.println("Caught IOException");
    }

     

    위 코드는 Parent 참조로 display()를 호출하기 때문에, IOException만 처리하는데, Child의 display()가 SQLException을 던질 경우, 이 예외는 처리되지 않고 프로그램이 비정상적으로 종료될 것이다. 이러한 상황을 방지하기 위해 자식 클래스의 오버라이딩 메서드는 부모 메서드가 던지는 예외와 같거나 더 적은 범위의 예외만 던질 수 있는 것이다.

    'Java' 카테고리의 다른 글

    클래스와 객체의 이해  (0) 2024.11.20
    JDK와 JRE의 차이  (0) 2024.11.20
    접근제어자 캡슐화, 정보 은닉  (0) 2024.11.20
    String, Stringbuffer, Stringbuilder 차이  (0) 2024.11.20
    String 문자열 String Pool, ==과 equals() 차이점  (0) 2024.11.15

    댓글