[JAVA] 자바 부모클래스 및 인터페이스 심화: 오버라이딩과 메서드 동작

2025. 1. 17. 17:20·BackEnd/JAVA

1. 자바 부모 클래스와 인터페이스 메서드를 오버라이딩 하지 않게 하는 방법

자바에서 인터페이스나 부모 클래스의 메서드를 오버라이딩하지 않게 하려면 final 키워드를 활용하는 것이 핵심입니다. 하지만, 각각의 경우에서 어떻게 적용되는지 좀 더 자세히 설명드리겠습니다.

1.1 부모 클래스 메서드를 오버라이딩 하지 않게 하려면

부모 클래스에서 자식 클래스가 특정 메서드를 오버라이딩하지 못하게 하려면, 해당 메서드를 final로 선언해야 합니다. final로 선언된 메서드는 자식 클래스에서 오버라이딩할 수 없습니다.

class Parent {
    public final void someMethod() {
        // 이 메서드는 오버라이딩 불가
    }
}

class Child extends Parent {
    // 오버라이딩 시도 시 컴파일 에러 발생
    // @Override
    // public void someMethod() {
    //     // 컴파일 에러
    // }
}

즉, 부모 클래스에서 메서드를 final로 선언하면 해당 메서드는 자식 클래스에서 변경하거나 오버라이딩할 수 없습니다.

1.2 인터페이스 메서드를 오버라이딩 하지 않게 하려면

인터페이스의 경우 기본적으로 모든 메서드는 abstract로 정의되므로 구현 클래스에서 오버라이딩을 해야 합니다. 하지만, Java 8부터 인터페이스에 default 메서드와 static 메서드를 정의할 수 있게 되었습니다. 이 중에서 static 메서드는 오버라이딩이 불가능합니다.

interface MyInterface {
    static void someStaticMethod() {
        // 이 메서드는 오버라이딩 불가
    }

    default void someDefaultMethod() {
        // 이 메서드는 오버라이딩 가능
    }
}

class MyClass implements MyInterface {
    // static 메서드는 오버라이딩할 수 없음
    // @Override
    // public static void someStaticMethod() {
    //     // 컴파일 에러
    // }

    @Override
    public void someDefaultMethod() {
        // 오버라이딩 가능
    }
}

즉, 인터페이스에서는 static 메서드로 정의하면 오버라이딩을 막을 수 있습니다. 하지만 default 메서드는 구현 클래스에서 오버라이딩이 가능합니다.

1.3 추가: 클래스와 인터페이스의 상속 제한 차이

  • 클래스: 클래스에 final 키워드를 붙이면 해당 클래스는 상속할 수 없으며, 자식 클래스에서 메서드를 오버라이딩할 수 없게 됩니다.
final class Parent {
    public void someMethod() {
        System.out.println("부모 클래스의 메서드");
    }
}

// 컴파일 에러 발생: 'Parent' 클래스를 상속할 수 없음
class Child extends Parent {
    // 오버라이딩 시도 불가
}
  • 인터페이스: 인터페이스는 final로 선언할 수 없으며, 다른 클래스에서 항상 구현 가능합니다. 자바의 설계 철학 상, 인터페이스는 행동의 규격을 정의하는 역할을 하기 때문에 구현을 제한할 수 없습니다.

2. 자바 인터페이스에서 static 메서드와 default 메서드 정리

2.1 static 메서드

static 메서드는 인터페이스에 속한 메서드로, 구현 클래스에서 오버라이딩할 수 없고, 인터페이스 이름을 통해 직접 호출할 수 있습니다. 이 메서드는 특정 클래스의 인스턴스와는 관련이 없으며, 인터페이스 그 자체와 관련이 있습니다.

즉, 인터페이스의 static 메서드는 인터페이스 자체에서 호출해야 합니다.
자세히 말하면 인터페이스의 static 메서드는 구현 클래스의 객체를 통해 호출할 수 없습니다. static 메서드는 오직 인터페이스 이름을 통해서만 호출할 수 있습니다. 이 말은 인터페이스에 귀속된 메서드이기 때문에, 구현 클래스의 인스턴스나 클래스 이름을 통해 호출할 수 없습니다.

자세히 설명하자면, static 메서드는 인스턴스와는 무관하게 인터페이스 수준에서 작동합니다. 이를테면, MyClass가 MyInterface를 구현하더라도, MyClass 타입의 객체를 통해 static 메서드를 호출할 수 없으며, 인터페이스 이름을 통해서만 호출이 가능합니다.

interface MyInterface {
    static void staticMethod() {
        System.out.println("인터페이스의 static 메서드");
    }
}

class MyClass implements MyInterface {
    // 구현 클래스에서 static 메서드를 오버라이딩할 수 없음
}

public class Main {
    public static void main(String[] args) {
        // 올바른 호출 방식 - 인터페이스 이름으로 호출
        MyInterface.staticMethod();  // 출력: "인터페이스의 static 메서드"

        // 잘못된 호출 방식 - 컴파일 에러 발생
        MyClass myClass = new MyClass();
        // myClass.staticMethod();  // 오류: MyClass의 인스턴스로는 static 메서드 호출 불가 (컴파일 에러 발생)
    }
}

위 코드에서 보듯이, static 메서드는 인터페이스의 이름을 통해 직접 호출할 수 있습니다. MyInterface.staticMethod()와 같은 방식으로 사용하며, 이는 인터페이스를 구현한 클래스와는 상관없이 사용할 수 있습니다. 인터페이스의 static 메서드는 해당 인터페이스에 귀속되며, 객체 인스턴스나 구현 클래스와는 무관합니다.

2.2 default 메서드

default 메서드는 자바 8에서 추가된 기능으로, 인터페이스에서 기본 구현을 제공하는 메서드입니다. 구현 클래스에서 이 메서드를 오버라이딩할 수 있지만, 오버라이딩하지 않으면 기본적으로 제공된 구현이 사용됩니다.

구현된 클래스의 인스턴스를 통해서 객체를 생성한 후 호출할 수 있습니다.

interface MyInterface {
    default void defaultMethod() {
        System.out.println("인터페이스의 default 메서드");
    }
}

class MyClass implements MyInterface {
    // default 메서드를 오버라이딩하지 않음
}

public class Main {
    public static void main(String[] args) {
        MyClass myClass = new MyClass();
        myClass.defaultMethod();  // 출력: "인터페이스의 default 메서드"
    }
}

여기서 defaultMethod()는 MyClass가 MyInterface를 구현하고 있지만, 오버라이딩하지 않은 경우 인터페이스의 기본 구현이 호출됩니다. 구현 클래스의 객체를 통해 호출할 수 있으며, 이 메서드는 인스턴스 메서드로 동작합니다.

자바8에서 인터페이스는 왜 default 메서드가 추가되었는지 그 이유가 명확하게 나와있습니다.

추상에 기반한 디자인에 따르면 인터페이스는 일반적으로 하나 혹은 다수의 구현 클래스들을 가지고 있는데, 만약 인터페이스에 새로운 메서드가 추가된다면 그 추가된 수 만큼 구현 클래스들은 강제적으로 구현을 해야합니다. 그렇지 않으면 이 디자인은 바로 무너져 내립니다.

인터페이스의 default 메서드는 이 이슈를 효울적으로 해결할 수 있습니다. 인터페이스에 새로운 default 메소드가 추가되면 자동적으로 구현 클래스에서도 사용할 수 있게 됩니다. 즉, 구현 클래스들을 수정할 필요가 없어집니다.

이렇게 구현 클래스를 수정하지 않고 깔끔하게 하위 호환 (backward compatibility)이 가능하게 합니다.

2.3 정리

  • static 메서드:
    • 인터페이스 이름을 통해 호출
    • 구현 클래스에서 오버라이딩 불가
    • 구현 클래스와 무관하게 인터페이스 자체에서 호출 가능
    • 구현 클래스나 인스턴스를 통해서는 static 메서드 호출 불가
  • default 메서드:
    • 구현 클래스에서 오버라이딩 가능
    • 구현 클래스의 인스턴스를 통해 호출
    • 오버라이딩하지 않으면 기본 구현이 사용됨.

따라서, 인터페이스의 static 메서드는 단순히 인터페이스 이름을 통해 호출할 수 있는 메서드로 사용할 수 있고, 구현 클래스에서는 해당 메서드를 변경하거나 재정의할 수 없습니다. 반면, default 메서드는 구현 클래스의 인스턴스를 통해 호출되는 메서드로, 필요에 따라 구현 클래스에서 재정의할 수 있습니다.

'BackEnd > JAVA' 카테고리의 다른 글

[JAVA] 인터페이스 심화: 다중 상속, 다중 구현  (3) 2025.01.20
[JAVA] try-with-resources 정리  (0) 2025.01.19
[JAVA] 인터페이스 정리  (0) 2025.01.12
[JAVA] 추상 클래스 (Abstract Class) 정리  (0) 2025.01.09
[JAVA] 접근 지정자 (Access Modifiers) 정리  (1) 2025.01.06
'BackEnd/JAVA' 카테고리의 다른 글
  • [JAVA] 인터페이스 심화: 다중 상속, 다중 구현
  • [JAVA] try-with-resources 정리
  • [JAVA] 인터페이스 정리
  • [JAVA] 추상 클래스 (Abstract Class) 정리
개발자 동긔
개발자 동긔
배우고 느낀점들을 기록합니다. 열정 넘치는 백엔드 개발자로 남고싶습니다.
  • 개발자 동긔
    Donker Dev
    개발자 동긔
  • 전체
    오늘
    어제
    • Category (39)
      • BackEnd (23)
        • JAVA (15)
        • Spring & JPA (7)
      • Database (4)
      • Computer Science (2)
        • Network (0)
        • Security (0)
        • Web (1)
      • DevOps (6)
        • Docker (1)
        • Jenkins (0)
        • Monitoring (2)
        • CICD (1)
      • 트러블 슈팅 (3)
      • 성능 개선 (1)
      • Project (0)
  • 인기 글

  • 태그

    Spring
    docker compose
    mysql master/slave replication
    SSH
    spring boot
    @RequestBody
    master/slave db 이중화 처리
    restful api 설계
    spring cloud msa
    interface
    JPA
    와일드카드
    인터페이스
    docker
    Jenkins
    java
    Database
    CICD
    restful api
    nginx
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
개발자 동긔
[JAVA] 자바 부모클래스 및 인터페이스 심화: 오버라이딩과 메서드 동작
상단으로

티스토리툴바