일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 |
- BottomSheet
- apollo3
- remembercoroutinescope
- 안드로이드
- 2989번
- JCF
- compose
- producestate
- State
- genarics
- ModalBottomSheet
- 양과 늑대
- derivedstateof
- rememberupdatedstate
- viewbinding
- mutableStateOf
- 2022 KAKAO BLIND RECRUITMENT
- snapshotflow
- 클린아키텍처
- mutablestate
- 선언형ui
- clean coder
- 명령형 ui
- Java
- 명령형ui
- 선언형 ui
- 뷰바인딩
- 자바
- 2022 kakao blind
- bottomscaffold
- Today
- Total
버미
자바 인터페이스와 추상 클래스 본문
인터페이스와 추상 클래스 각각 알아보고 비슷해보일 수도 있는 이 둘은 어떤 차이점이 있는이 알아보자.
🔍 추상 클래스는 abstract 메소드를 사용한 추상 메소드를 하나 이상 가진다. 인터페이스는 abstract 메소드를 가지며 다른 블로그를 살펴 보면 인터페이스도 추상 클래스의 일부분이라고 하는 글도 있다. 과연 인터페이스가 추상 클래스의 일부분일까?라는 의문점을 시작으로 이 글을 작성했다.
인터페이스
인터페이스는 다른 클래스를 작성할 때 기본이 되는 틀을 제공해주는 역할이다. 여러 종류의 객체를 만들어야하는 상황에서 작업 대상이 늘어날수록, 코드가 복잡해진다. 이 경우, 확장성과 유지보수성을 위해 인터페이스를 사용한다.
예를 들어, 고양이는 생선을 먹고 강아지는 뼈다귀를 먹는다고 하자.
인터페이스를 사용한다면 아래와 같이 코드를 작성할 수 있다.
interface Pet {
String feed();
}
class Cat implements Pet {
@Override
public String feed() {
return "fish";
}
}
class Dog implements Pet {
@Override
public String feed(){
return "born";
}
}
public class Main {
public static void main(String[] args) {
Pet cat = new Cat();
Pet dog = new Dog();
System.out.println("Cat feeds: " + cat.feed());
System.out.println("Dog feeds: " + dog.feed());
}
}
Java8 버전부터는 인터페이스에 default 메소드와 정적메소드를 작성할 수 있다.
모든 애완 동물은 잠을 잔다고 가정하고, 애완 동물 중에서 사족 보행하는 동물의 비율이 많기 때문에 다음과 같이 설계할 수 있다.
interface Pet {
String feed();
static void sleep() {
System.out.println("Sleep...");
}
default int getNumberOfPetLegs() {
return 4;
}
}
앵무새나 다른 이족 보행하는 애완동물인 경우는 getNumberOfPetLegs을 오버라이딩해서 바꾸면 된다.
즉, 클래스의 종류에 따라 구현부가 바뀌는 것을 추상 메소드로 정의하고 인터페이스의 유틸리티성 기능이라면 정적 메소드를 사용하면 된다. 공통 기능을 기본값으로 제공하면서, 필요에 따라 구현체에서 오버라이드하고자 한다면 default 메소드를 사용하면 된다.
추상 클래스
추상클래스도 다른 클래스를 작성할 때 기본이 되는 틀을 제공해주는 역할이다. 추상화를 한다는 점에서는 인터페이스와 비슷하지만, 차이점이 존재한다.
먼저 추상 클래스의 사용법에 대해 간단히 살펴보자.
class 앞에 abstract 키워드를 붙여 추상 클래스임을 명시한다. abstract을 사용한 추상 메소드를 하나 이상 가지고 있다면 추상 클래스가 될 수 있다. 인터페이스와는 달리, 추상 클래스는 인스턴스 변수를 가질 수 있으며 생성자를 super를 이용해 호출 할 수 있다.
abstract class Pet {
abstract String feed();
static void sleep() {
System.out.println("Sleep...");
}
int getNumberOfPetLegs() {
return 4;
}
}
class Cat extends Pet {
@Override
public String feed() {
return "fish";
}
}
class Dog extends Pet {
@Override
public String feed(){
return "born";
}
}
의도적으로 동일한 기능을 하도록 Pet을 인터페이스와 추상 클래스로 만들었다. 이렇게만 보면 모두 OCP의 원칙을 잘 지키며 동일하게 기능을 수행할 수 있는데 굳이 인터페이스와 추상 클래스를 나눠둔 이유는 뭘까?
이 둘을 구분해 둔 이유는 설계 목적과 사용 방식의 차이 때문이다.
구분하는 이유
- 상속 구조의 유연성(다중 상속 지원)
인터페이스는 다중 구현(implements)이 가능해, 여러 타입의 역할을 동시에 부여할 수 있다.
추상 클래스는 단일 상속만 가능하므로, 하나의 계층 구조에서만 확장할 수 있다. - 설계 의도와 추상화 수준
추상 클래스는 공통된 속성과 동작을 가진 계층 구조(상속 관계, extends)를 만들 때 사용한다. 즉, 여러 클래스의 공통 부분(상태와 동작)을 물려주고 싶을 때 쓰인다.
인터페이스는 기능의 명세를 제공하고, 관련 없는 클래스들도 동일한 동작을 하도록 강제할 때 사용한다.
예를 들어, 서로 다른 계층에 속한 클래스라도 특정 기능(예: Comparable, Swimmable)을 구현할 수 있다. - 추상 클래스는 상수, 인스턴스 변수, 생성자, 구현 메서드 등 다양한 요소를 가짐
인터페이스는 상수(public static final)와 추상 메서드, 그리고 (자바8 이후) default/static 메서드만 가질 수 있다
객체 지향 프로그래밍 관점에서 "추상화"한다는 점을 공통적으로 가지고 있을 뿐이며, 인터페이스와 추상 클래스는 상하 관계나 포함 관계가 아니다.
인터페이스는 자식 클래스에서 사용하기 위해서는 implements 키워드를 사용하고 추상 클래스는 extends 키워드를 사용하는 것을 생각해보면 이해가 쉬울 것이다.
결론
추상 클래스: 공통 속성·동작을 가진 계층 구조 설계, "is-a" 관계(상속)에서 사용.
인터페이스: 기능 명세, "can-do" 관계(역할, 능력)에서 사용. 다중 구현 가능, 유연한 타입 설계.
'Language > Java' 카테고리의 다른 글
자바 컬렉션 프레임 워크 (Java Collections Framework) (0) | 2024.06.24 |
---|---|
자바 제네릭(Generics) 개념 & 문법 (0) | 2024.06.22 |