[JAVA]추상 클래스와 인터페이스의 차이

Inung_92·2023년 2월 27일
2

JAVA

목록 보기
10/15
post-thumbnail

추상클래스와 인터페이스란?

⚡️ 추상 클래스

📖하나 이상의 추상 메소드를 보유하고 있거나 abstract 키워드가 붙은 미완성 클래스

⚡️ 인터페이스

📖추상 메소드와 상수만으로 구성되어 있으며 클래스의 기본 틀을 제공하는 일종의 추상 클래스
(자바 8부터 default 메소드도 지원)

아직 추상 클래스와 인터페이스에 대한 개념을 알아보지 못하였다면 아래 링크들을 참고하여 간단히 알아보고오자.

추상클래스인터페이스 클릭


추상클래스와 인터페이스의 차이

앞서 알아본 추상클래스와 인터페이스의 차이를 알아보기 전에 먼저 공통점을 알아보자.

⚡️ 공통점

  • new 연산자를 사용하여 직접 인스턴스 생성불가
  • 추상 메소드와 상수를 보유 가능
  • 상속 또는 구현 객체를 통해 인스턴스 생성

위 세가지 정도가 추상 클래스와 인터페이스의 공통점이다. 추상 클래스와 인터페이스의 공통점을 코드로 비교해보자.

🖥️ 추상클래스와 인터페이스

//추상 클래스 선언
public abstract class Car{
	//상수보유
	public static final int PRICE=1000;

	//추상 메소드 보유
    public abstract void move();
    //키워드 생략가능
    public void stop();
}

//인터페이스 선언
public interface ElectronicCar{
	//상수 보유
    public static final int CAPACITY = 1000;
    //추상 메소드 보유
    public abstract void charge();
}

이제 본격적으로 두 객체의 차이를 알아보자.

⚡️ 차이점

  • 추상클래스는 생성자와 상태를 가질 수 있지만 인터페이스는 불가능
  • 추상클래스는 다중상속을 지원하지 않으며, 인터페이스는 다중구현을 지원
  • 추상클래스는 공통점을 가진 서브 클래스들이 슈퍼클래가 가진 상태 및 기능을 구현해야할 경우 사용하며, 인터페이스는 기능에 중점을 두고 동일한 기능을 수행해야하는 클래스들이 구현할 경우 사용

첫번째 차이점에 대한 예시를 보자.

🖥️ 생성자와 상태

//추상클래스
public abstract class Car{
	//상태보유
    private int price;
    private String brand;
    
    //생성자(new가 없기 때문에 상속받은 서브클래스에서 super키워드를 통해 접근가능)
    public Car(int price, String brand){
    	this.price = price;
        this.brand = brand;
    }
}

//인터페이스
public interface ElectronicCar{
	//상태보유 불가능
    //생성자 메서드 없음
}

추상클래스는 다들 알고 있는 것처럼 생성자 메서드를 보유하고는 있으나 new를 통해 직접 인스턴스를 생성할 수는 없다. 그렇기에 상속받은 클래스가 super키워드를 통해 슈퍼클래스의 상태를 초기화해 줄 수 있다. 반면에 인터페이스는 생성자 메서드 자체가 없고, 상수만 보유할 수 있기 때문에 이 부분에서 둘의 차이가 극명하게 나는 것이다.

두번째 차이점에 대한 예시를 보자.

🖥️ 다중상속과 다중구현

//추상클래스 상속
public abstract class Car{
	//상태보유
    private int price;
    private String brand;
    
    //생성자(new가 없기 때문에 상속받은 서브클래스에서 super키워드를 통해 접근가능)
    public Car(int price, String brand){
    	this.price = price;
        this.brand = brand;
    }
    
    //추상메소드
    public void move();
}

//상속받은 서브클래스(단일상속)
public class MiniCar extends Car{
	int speed;
	//생성자 메서드 접근
	public MiniCar(int price, String brand){
    	super(price, brand);
    }

	//추상메소드 구현
    public void move(){
    	speed++;
    }
}

//인터페이스 구현
public interface CampingCar{
	public void openCeil();
}

public interface ElectronicCar{
	public void charge();
}

//구현 클래스(다중구현)
public class MyCampingCar implements CampingCar, ElectronicCar{
	@Override
	public void openCeil(){
    	//구현부 작성
    }
	@Override
    public void charge(){
    	//구현부 작성
    }
}

위에서 본 것처럼 클래스는 기본적으로 상속관계에서 다중상속을 지원하지 않는다. 같은 메소드명을 보유하고 있거나 동일한 상태를 가질 때의 모호성 때문에 이러한 기능을 지원하지 않는 것이다. 반면에 인터페이스는 기능을 중심으로 선언되기 때문에 구현하는 클래스에서 기능에 대한 틀이 제공되어지길 원한다면 얼마든지 인터페이스를 구현할 수 있다.

마지막 세번째는 코드보다는 위의 두 내용을 합쳐 놓은 것이다.
추상 클래스는 상속 관계 내에서 공통점이 같은 클래스들에게 상태를 제공하고, 추상 메소드에 대한 강제구현을 의도하지만 인터페이스의 경우에는 상태를 보유하지 못하니 기능에 중점을 두고 각 클래스가 알맞은 기능을 사용하거나 혹은 클래스들에게 기본적인 틀을 제공하기 위해 구현하도록 강요하는 의도를 가지고 있는 것이다.


마무리

정리를 하자면 클래스 간의 상속관계에서 단일 상속만 지원을 하기 때문에 더욱 유연하게 다형성을 적용받기 위해서는 인터페이스를 활용하는 방법도 있을 것이다.
하나의 클래스만 상속받은 클래스보다는 하나의 클래스를 상속받고 여러개의 인터페이스를 구현하는 클래스가 다형성을 지원하기에는 더 유연한 객체가 될 수 있을테니 말이다.

주의할 점은 하나의 인터페이스가 너무도 다양한 기능(틀)을 제공하는 경우에는 불필요한 강제구현을 의도할 수 있으니 이런 부분은 주의해야한다. 만약 프로그램 내에서 클래스가 구현해야할 기능이 많은 경우 인터페이스를 분리하는 방법이 더 적절할 것으로 생각된다.

그럼 이만.👊🏽

profile
서핑하는 개발자🏄🏽

0개의 댓글