JAVA
15. Default Method & 추상 클래스 & 인터페이스
ggomjiu
2025. 4. 29. 01:58
Default Method
1. 개요
- 배포된 인터페이스에서 수정이 어려운 단점을 극복하게 됨
- Java 9) private Method를 선언해 외부에서 접근 불가능한 mehtod 또한 선언할 수 있게 됨
- EX)
interface Foo {
String getName(); // 추상 메서드, 구현하는 클래스에서 무조건 구현해줘야 하는 메서드.
}
---
public class Bar implements Foo {
private String name;
public Bar(String name) { // 생성자
this.name = name;
}
@Override
public String getName() { // 추상 메서드 구현
return this.name;
}
}
---
public class Main {
public static void main(String[] args) {
Foo foo = new Bar("Neo");
System.out.println(foo.getName());
}
}
---
Result
>> Neo
- 이전의 방식 ) 인터페이스에 새로운 printName() 메서드를 추가하고 인터페이스 Foo를 구현한 모든 클래스에서 새로운 메서드를 구현했어야 함
- Default Method EX)
interface Foo {
String getName(); // 추상 메서드, 구현하는 클래스에서 무조건 구현해줘야 하는 메서드.
void printName() {
System.out.println(getName());
}
}
---
public class Bar implements Foo {
private String name;
public Bar(String name) { // 생성자
this.name = name;
}
@Override
public String getName() { // 추상 메서드 구현
return this.name;
}
}
---
public class Main {
public static void main(String[] args) {
Foo foo = new Bar("Neo");
foo.printName();
}
}
---
Result
>> Neo
2. 주의
- 다중 상속시 같은 이름의 메서드가 두 인터페이스에 모두 존재할 때, 구현 클래스에서 재정의해서 사용해야 함
- EX)
interface Foo {
void sameNameMethod();
}
---
interface Bar {
void sameNameMethod();
}
---
class Impl implements Foo, Bar {
...
}
---
public class Main {
public static void main(String[] args) {
Impl impl = new Impl();
impl.sameNameMethod(); // 모른다! 메서드! 뱉어낸다! 에러!
}
}
---
Result
>> Error : Main inherits unrelated defaults...
- 구현하는 클래스에서 메서드를 재정의해서 사용해야 함
interface Foo {
void sameNameMethod();
}
---
interface Bar {
void sameNameMethod();
}
---
class Impl implements Foo, Bar {
@Override
publci void sameNameMethod() {
System.out.println("sameNameMethod called!");
}
}
---
public class Main {
public static void main(String[] args) {
Impl impl = new Impl();
impl.sameNameMethod(); // 안다! 메서드! 뱉어낸다! 결과!
}
}
---
Result
>> sameNameMethod called!
- 디폴트 메서드는 equals(), hashcode()와 같은 Object 클래스의 메서드를 재정의 할 수 없음
- 정적 메서드는 재정의 할 수 없음
- 인터페이스 간 상속관계에 따라 우선순위가 달라짐
- IF) interface A extends B처럼 인터페이스 A가 B를 상속받고, B에서 정의된 디폴트 메서드를 재정의 할 경우, A의 디폴트 메서드가 우선순위를 가짐
- IF) class C implements A처럼 A가 B를 상속받고, 그 상속받은 인터페이스를 C가 구현해 디폴트 메서드를 재정의 한 경우, C의 재정의된 메서드가 우선권을 가짐
추상 클래스 vs 인터페이스
- 추상 클래스와 인터페이스는 쓰임이 다름
1. 공통점
- 스스로 new 연산자를 통해 객체를 생성할 수 없음
- 추상 메서드를 가짐
- 자손 클래스를 이용해 정의된 추상 메서드들을 구현해야 함
2. 용도, 태생
- 추상 클래스
- 여러 클래스를 추상화해 공통점을 묶은 추상 클래스를 상속받아 그 기능을 사용하거나 확장하기 위함
- 인터페이스
- 여러 구현체들의 맥락에 맞는 동일한 동작을 보장하기 위한 명세
3. 다중 상속 가능 여부
- 추상 클래스
- 다중 상속 불가능
- 인터페이스
- 다중 상속 가능
4. 선언 가능한 메서드
- 추상 클래스
- 일반 클래스와 동일하고, 추상 메서드를 선언할 수 있음
- 인터페이스
- 추상 메서드만 선언할 수 있었으마, Java8부터 디폴트 메서드, Java9부터 정적 메서드까지 선언 가능하게 됨
5. 변수와 생성자, 메서드
- 추상 클래스
- 생성자, 변수, 메서드를 모두 가질 수 있음
- 인터페이스
- 메서드와 정적 상수만 가질 수 있음
- Java8 이전까지는 추상 메서드만, Java9 이전까지는 추상 메서드 + 디폴트 메서드, 그 이후로는 추상 메서드 + 디폴트 메서드 + private메서드만 가질 수 있음
6. 자식 클래스에서의 구현의 강제성
- 추상 클래스
- 선택적으로 오버라이딩 가능
- 인터페이스
- 정의된 모든 추상 메서드를 구현해야 함
- 디폴트 메서드의 경우 선택적으로 구현 가능
7. 키워드
- 추상 클래스
- extends
- 인터페이스
- implements