Intro.

책에서는 오버라이딩과 오버로딩에 대해서 11 가지 이상의 질문을 다루고 있다. 그리고 해당 개념을 말하면서 말하게 되는 연계된 개념들이 있는데 해당 개념들을 같이 묶어서 소개하는 것이 중요하다고 생각되서 이를 같이 다루고자 한다. :) 분량이 많더라도 재밌으면 좋겠다.

1. 자바에서 공변 메서드 오버라이딩이란 무엇인가?

공변(covariant) 메서드 오버라이딩을 사용하여 오버라이딩 메서드는 실제 반환 타입의 하위 타입을 반환할 수 있습니다. 공변은 함께 변한다는 의미로 여기에서는 오버라이딩 메서드의 클라이언트가 반환된 타입의 명시적인 타입 변환을 하지 않아도 된다는 의미입니다. 예를 들어 자바의 clone 메서드는 Object를 반환합니다. 즉, 이 메서드를 활용하여 복제된 객체를 반환받고자 할 때 Object를 받아서 Object의 서브클래스로 명시적으로 타입 변환하여 원하는 실제 결과를 만들어야 합니다. 그러나 자바 5부터는 공변 메서드 오버라이딩이 지원되기 때문에 clone 메서드를 오버라이드하여 Object 대신에 필요한 서브클래스를 직접 반환할 수 있습니다.

‘자바에서 공변 메서드르 오버라딩이란 무엇인가?와 같은 질문에는 거의 항상 예제를 답에 포함해야 하므로 Cloneable(복제 가능한) 인터페이스를 구현하는 Rectangle 클래스를 살펴보겠습니다. clone 메서드는 다음과 같이 Object 대신 Rectangle을 반환할 수 있습니다.

public class Rectangle implements Cloneable {
    private final int height;
    private final int width;

    public Rectangle(int height, int width) {
        this.height = height;
        this.width = width;
    }

    public int getHeight() {
        return height;
    }

    public int getWidth() {
        return width;
    }

    @Override
    protected Rectangle clone() throws CloneNotSupportedException {
        Rectangle clone = (Rectangle) super.clone();

        return clone;
    }
}

clone 메서드를 호출할 때 명시적인 캐스팅이 필요 없습니다.

public class Main {
    public static void main(String[] args) throws CloneNotSupportedException {
        Rectangle r = new Rectangle(4, 3);
        Rectangle clone = r.clone();

        System.out.println("Width: " + clone.getWidth());
        System.out.println("Height: " + clone.getHeight());
    }
}

공변 메서드 오버라이딩과 관련한 간접적인 질문에 주의해야 합니다. 예를 들어 오버라이드 할 때 메서드의 반환 타입을 서브클래스로 변경 할 수 있는가? 와 같은 질문을 받을 수 있습니다. 이 질문에 대한 답은 이 섹션에 다룬 자바에서 공변 메서드 오버라이딩이란 무엇인가?라는 질문에 대한 답과 동일합니다.

2. 오버라이딩 및 오버로딩 메서드에서 예외를 다룰 때 주요 제한 사항은 무엇인가?

해당 질문에 관해 아래와 같이 답변해 보자.

먼저, 오버라이딩 메서드에 관해 말씀 드리겠습니다. 확인되지 않은 예외의 경우 오버라이딩 메서드에서 사용하는 데 아무런 제한 사항이 없습니다. 오버라이딩 메서드는 모든 Runtime-Exception, 즉 확인되지 않은 예외를 발생시킬 수 있습니다. 반면에 확인된 예외의 경우 오버라이딩 메서드는 오버라이드된 메서드의 확인된 예외 혹은 그 서브 클래스 예외만 발생시킬 수 있습니다. 다시 말해 오버라이딩 메서드는 오버라이된 메서드에서 발생된 확인된 예외보다 넓은 범위를 가진 확인된 예외는 발생시킬 수 없습니다. 예를 들어, 오버라이드된 메서드가 SQLException을 발생시킨다면 오버라이딩 메서드는 BatchUpdateException과 같은 서브클래스의 예외는 발생시킬 수 있지만 Exception 과 같은 슈퍼클래스의 예외는 발생시킬 수 없습니다.
두 번째로 오버로딩 메서드에 관해 말씀드리겠습니다. 오버로딩 메서드는 예외를 다룰 때 어떤 제한 사항도 없습니다. 이것은 필요에 따라 throw 문을 얼마든지 수정할 수 있다는 의미입니다.

해당 내용의 예제는 아래와 같이 제시할 수 있습니다.

import java.sql.SQLException;

public class Clazz {
    public void foo(String foozzy) {
        System.out.println("Executing Clazz#foo() that doesn't throw any exception");
    }

    public void foo() throws SQLException {
        System.out.println("Executing Clazz#foo() that throws SQLException");
        throw new SQLException("Cazz#foo() did this!");
    }

    public void foo(int foozzy) {
        System.out.println("Executing Clazz#foo() that throws RuntimeException");
        throw new RuntimeException("Clazz#foo(int foozzy) did this!");
    }
}

위와 같은 의도적인 오류를 만드는 클래스와 메인은 아래와 같이 구성할 수 있습니다.

import java.sql.SQLException;

public class Main {
    public static void main(String[] args) {
        Clazz clazz = new Clazz();
        clazz.foo("Foozzy");
        System.out.println();

        try {
            clazz.foo();
        } catch (SQLException ex) {
            System.err.println(ex);
        }
        
        System.out.println();

        try {
            clazz.foo(1);
        } catch (RuntimeException ex) {
            System.err.println(ex);
        }
    }
}

결과는 아래와 같습니다.

Executing Clazz#foo() that doesn't throw any exception

Executing Clazz#foo() that throws SQLException
java.sql.SQLException: Cazz#foo() did this!

Executing Clazz#foo() that throws RuntimeException
java.lang.RuntimeException: Clazz#foo(int foozzy) did this!

3. 슈퍼클래스의 오버라이드된 메서드를 서브클래스의 오버라이딩 메서드에서 어떻게 호출할 수 있는가?

자바의 super 키워드를 이용해서 슈퍼클래스의 오버라이된 메서드를 서브클래스의 오버라이딩 메서드에서 호출할 수 있습니다. 예를 들어 foo 메서드를 가지는 슈퍼클래스 A가 있고, A의 서브클래스 B가 있다고 하겠습니다. 서브클래스 B에서 foo 메서드를 오버라이드 했을 때 오버라이딩 메서드에서 super.foo를 호출하면 오버라이드된 메서드인 A의 foo를 호출할 수 있습니다.

4. main 메서드를 오버라이드 또는 오버로드할 수 있는가?

main 메서드가 static 메서드라는 사실을 명심해야 합니다. main 메서드는 오버로드할 수 있지만 오버라이드 할 수 없습니다. 오버라이드할 수 있는 메서드는 객체 타입에 따라 런타임에 결정되는 반면 static 메서드는 컴파일 타임에 결정되기 때문에 main 메서드를 오버라이드 할 수 없습니다.

5. 자바에서 static이 아닌 메서드를 static 메서드로 오버라이드할 수 있는가?

아닙니다. static이 아닌 aptjemsms static 메서드로 오버라이드 할 수 없습니다. 또한 그 반대의 경우도 불가능합니다. 두 가지 경우 모두 컴파일 에러가 발생합니다.

6. 다형성, 오버라이딩, 오버로딩의 차이점은 무엇인가?

이 질문의 맥락에서 오버로딩 기법은 컴파일 타임 다형성으로 알려져 있는 반면에 오버라이딩 기법은 런타임 다형성으로 알려져 있습니다. 오버로딩은 정적 혹은 이른 바인딩을 사용하는 반면에 오버라이딩은 동적 혹은 늦은 바인딩을 사용합니다.

7. 바인딩 작업이란 무엇인가?

바인딩 작업은 코드 라인에서 참조한 결과로 호출할 메서드 또는 변수를 결정합니다. 즉, 메서드 호출을 메서드 본문에 연결하는 과정을 바인딩 작업이라고 합니다. 일부 참조는 컴파일 시간에 바인딩되는 반면에 다른 참조는 런타임에 바인딩됩니다.
런타임에 바인딩되는 참조는 객체의 타입에 따라 다릅니다. 컴파일 시간에 바인딩되는 참조는 정적 바인딩 작업이라고 하며 런타임에 바인딩되는 참조는 동적 바인딩 작업이라고 합니다.

8. 정적 바인딩과 동적 바인딩의 주요 차이점은 무엇인가?

우선 정적 바인딩은 컴파일 시간에 ㅂ라생하며 동적 바인딩은 런타임에 발생합니다. 두 번째 차이점은 private, static,final 메서드 혹은 변수는 정적 바인딩을 사용하는 반면에 가상 메서드는 객체의 타입에 따라 런타임에 바인딩됩니다.
즉, 정적 바인딩은 Type(자바의 클래스) 정보를 통해 결정되며 동적 바인딩은 Object에 의해 결정됩니다. 다시 말해 정적 바인딩에 의존하는 메서든느 객체와 연관이 없으며 Type에 의해 호출되고 동적 바인딩에 의존하는 메서드는Object와 관련이 있습니다. 정적 바인딩에 의존하는 메서드의 실행은 동적 바인딩에 의존하는 메서드보다 아주 조금 더 빠릅니다.
정적과 동적 바인딩은 다형성에서도 사용됩니다. 정적 바인딩은 컴파일 타임 다형성(오버로딩 메서드)에 쓰이고 동적 바인딩은 런타임 다형성(오버라이딩 메서드)에 쓰입니다. 정적 바인딩은 컴파일 시간 성능에 오버헤드(overhead)를 더하고 동적 바인딩은 런타임 성능에 오버헤드를 더하기 때문에 정적 바인딩이 더 선호됩니다.

9. 자바에서 가상 메서드를 작성할 수 있는가?

네 작성할 수 있습니다. 사실 자바에서 static이 아닌 메서드는 모두 기본적으로 가상 메서드입니다. private 또는 final 키워드로 표시하여 가상이 아닌 메서드를 작성할 수 있습니다. 즉, 다형 동작을 위해 상속될 수 있는 메서드는 가상 메서드입니다.
또는 이 명제를 뒤집어서 말하면 상속할 수 없는 private 메서드와 오버라이드할 수 없는 final 메서드는 가상 메서드가 아닙니다.

10. 추상화와 다형성의 차이점은 무엇인가?

추상화와 다형성은 상호의존적인 두 가지 기본적인 객체지향 프로그래밍 개념을 나타냅니다. 추상화는 갭라자가 재사용 및 맞춤형 정의가 가능한 일반적인 솔루션을 설계할 수 있게 하는 반면에 다형성은 개발자가 런타임에 실행해야 하는 코드 선택을 미룰 수 있게 합니다. 추상화가 인터페이스와 추상 클래스를 통해 구현되는 반면에 다형성은 오버라이딩과 오버로딩 기법으로 구현됩니다.

11. 다형성을 구현하는 방법으로 오버로딩을 고려할 수 있는가?

이것은 논쟁의 여지가 있는 주제입니다. 어떤 사람들은 오버로딩을 다형성이라고 여기지 않기 때문에 컴파일 타임 다형성의 개념을 받아들이지 않으며, 오버라이딩 메서드만이 진정한 다형성이라고 주장합니다.
이러한 목소리 뒤에는 오버라이딩만이 런타임 조건에 따라 코드가 다르게 동작할 수 있게 한다는 주장이 있습니다. 즉, 다형성 동작을 나타내는 것은 메서드 오버라이딩의 특권이라는 의미입니다.

Outro

다음 주제는 분량에 따라 조절이 있겠지만 주로 인터페이스 즉, 추상황와 관련한 부분을 다루고 질문에 관한 마지막 파트에서는 디자인 패턴에 관한 질문을 주로 다루고자 한다. :) 조금 긴 글이었지만 막상 이러한 질문들에 대해 깊이 있게 고민해 보고 할게 30가지 정도고 이것들을 밑천으로 해서 좋은 개발 역량을 만들 수 있다면 가치 있는 것이지 않을까 생각해 본다 :)

profile
하루 하루 즐겁게

0개의 댓글