많이 유사하지만 다른 인터페이스(Interface)와 추상클래스(abstract class)의 차이에 대해서 알아보도록 하겠습니다.
extend, implement 등의 기본적인 사용법은 쓰지 않겠습니다.
Interface
구현에 의존적
interface는 특정 기능을 수행하자는 일종의 contract 즉 사전 합의가 주된 목적이기 때문에 interface를 사용하는
의도를 만족시키기 위해서는 implementation 죽 구현에 의존한다
즉 concrete class로 반드시 구현되어야 하는 일종의 contract인 것.
상태를 갖지 못한다
인터페이스는 state 즉 상태를 갖지 못한다.
interface에서의 variable은 전부 static final 이다.
변경 가능한 인스턴스 변수를 사용할 수 없으며 오직 final 변수 즉 변경 가능하지 못한 immutable variable만 사용 가능하다.
public interface levelUp{
int number = 7;
String name = "자기개발자";
}
두 변수는 상수이며 인스턴스에 의존적이지 않고 변경될 수가 없다
값을 변경하려고 한다면 컴파일 에러가 발생함.
함수형 인터페이스(Java8)
abstract method가 오직 하나뿐인 함수형 인터페이스로 생성이 가능하다.
@functionalInterface 에너테이션으로 함수형 인터페이스 인지 아닌지 체크가 가능하다.
@FunctionalInterface
public interface Supplier<T> {
/**
* Gets a result.
*
* @return a result
*/
T get();
}
Default Method
Default Method는 Java8에서 도입되었다.
Default Method는 Abstract Method와는 다르게 Interface 내부에서 구현이 있을 수 있다.
Default Method가 도입되고 "사실 interface는 abstract class와 큰 차이가 없는 것이 아니야?"라고 생각할 수도 있지만.
인터페이스는 state를 가질 수 없기 때문에 사실이 아니다.
public class DefaultMethodExample {
public static void main(String[] args) {
Tester tester = new SelfTester();
challenger.doChallenge();
}
}
class SelfTester implements Tester { }
interface Tester {
default void doTest() {
System.out.println("자기개발자 test!!");
}
}
여기서의 포인트는 Default Method들의 인스턴스 생성을 통한 구현이 필요하다는 것.
Default Method는 static 과같이 사용할 수 없고 static일 수가 없다.
interface를 사용하는 경우
interface는 decoupling(디커풀링) 즉 모듈, 객체 간 의존성을 낮추고
다형성을 구현하는데 매우 유용하다.
많은 클래스들이 동일한 상위 클래스에 속해 있고 동일한 method action을 갖고 있지만 다르게 동작하는 경우 interface를 활용하면 매우 좋다.
Abstract Class
State를 가질 수 있다.
추상 클래스는 인스턴스 변수가 있는 상태를 가질 수 있다.
즉 인스턴스 변수를 사용하고 변경할 수 있음을 의미한다.
public abstract class AbstractClassMutation {
private String name = "자기개발자";
public static void main(String[] args) {
AbstractClassMutation abstractClassMutation = new AbstractClassImpl();
abstractClassMutation.name = "변경된 값인 자기개발자";
System.out.println(abstractClassMutation.name);
}
}
class AbstractClassImpl extends AbstractClassMutation { }
// output -> 변경된 값인 자기개발자
Abstract methods
인터페이스와 마찬가지로 추상 클래스는 추상 메서드를 가질 수 있다.
abstract method 즉 추상 메서드는 method body가 없는 메서드이며
interface와는 다르게 명시적으로 abstract로 선언해야 함.
public abstract class AbstractMethods {
abstract void dosomething();
}
명시적으로 적지 않으면 컴파일 에러가 발생한다.
추상 클래스를 활용한 좋은 예시
템플릿 메서드 디자인 패턴은 추상클래스를 사용한 것에 대한 좋은 예시가 되어줌.
concrete method 내부에서 인스턴스 변수에 대한 값을 변경하면서 method를 구현하는 방식으로 적용.
현재 포스팅에서는 Interfaced와 abstract class의 관한 글이므로 템플릿 메서드 패턴에 대해서는 글을 작성하지 않겠습니다.
추후에 디자인 패턴 관련 포스팅을 할 예정이니 그때 추가되면 링크로 달아두도록 하겠습니다!.
그래서 Interface와 Abstract Class의 주된 차이점은 무엇일까?
1. OOP 즉 객체지향적 관점에서 본다면 interface와 abstract class의 가장 주된 차이점은
state 즉 상태 값을 가질 수 있는가 없는가 이다.
2. interface의 경우 하나 이상을 implement 할 수 있지만 abstract classs는 한 개만 extend가 가능하다.
예를 들어 물고기 클래스와 사람 클래스를 상속받은 인어 클래스가 있다고 가정해보자.
인어 클래스에서 숨쉬기라는 기능의 메서드를 호출한다면
물고기 클래스의 숨쉬기를 가져와야 할까? 사람 클래스의 숨쉬기를 가져와야 할까?
Diamond Problem이라고 불리는 위와 같은 문제 등의 이유로 자바는 다중 상속을 지원하지 않고 있다.
3. interface는 클래스로 구현하거나 interface로 확장할 수 있지만 추상 클래스는 extend를 통한 확장만 가능하다.
4. Lambda는 functional interface에서만 사용할 수 있는 반면 abstract method가 하나만 있는 abstract class는 Lambda를 사용할 수 없다.
표로 보는 차이점
Interface | Abstract Class |
오직 fnal static 변수만 사용 가능. interface는 스스로의 상태값을 변경 불가능. |
어떤 종류의 인스턴스변수 또는 static 변수를 가질 수 있고 그 변수의 값을 변경시킬 수도 있고 immutable 즉 불변으로 만들어서 사용할 수도 있다. state를 가질 수 있음. |
class는 여러가지의 interface를 implement 할 수 있다. | class는 호직 하나의 abstract class만 extend 가능하다 |
implement 키워드를 사용해서 구현이 가능하다. interface 끼리는 extends 사용할 수 있다. |
extends만 사용 가능. |
static fiianl 필드, 파라미터, 또는 메서드의 지역변수만 사용 가능. | 인스턴스 변수의 가변 필드, 파라미터, 지역 변수등을 가질 수 있다. |
funtional interface만 Lambda feature 사용 가능. | 오직 하나의 abstract method를 갖고있는 abstract class는 lambda를 사용 불가. |
생성자를 가질 수 없다. | 생성자를 가질 수 있다. |
abstract method를 가질 수 있다 default and static methods를 가질 수 있다. (java8 도입) private method를 가질 수 있고 implemenation이 가능 하다. (java9 도입) |
어떤 종류의 method든 다 가질 수 있음. |
언제 interface, abstract class를 사용하면 좋을까?
수정 가능한 상태 즉 가변 상태에 대한 구현이 필요한 경우에는 abstract class를 사용하는 것이 좋고
클래스의 state 즉 상태 값을 유지할 필요가 없는 경우에는 일반적으로 interface를 사용하는 것이 좋다.
참조
https://www.infoworld.com/article/2077421/abstract-classes-vs-interfaces-in-java.html
https://stuartmarks.files.wordpress.com/2015/10/con6851-api-design-v2.pdf
https://www.youtube.com/watch?v=o10ETyiNIsM&t=1440s&ab_channel=Java
'Programming Language > Java' 카테고리의 다른 글
[Java] 람다(Lambda)를 소화시켜 보자 (0) | 2023.01.08 |
---|---|
[Java] Functional Interface(함수형 인터페이스) (0) | 2023.01.08 |
[Java] Equals vs Hashcode 그리고 재정의 (0) | 2023.01.08 |
[EffectiveJava] 정적 팩터리 메서드(Static Factory Method) 장단점 (1) | 2022.11.19 |
[Java] 상속 vs 컴포지션 (1) | 2022.11.12 |
댓글