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) 정리 (0) | 2025.01.06 |