개발메모/간단정리

[간단정리] JAVA - 추상클래스, 인터페이스 특징 및 차이점 확실히 기억하기

99C0RN 2022. 8. 26. 20:06

개요

추상 클래스(Abstract Class)와 인터페이스(Interface)의 특징 및 차이점 알아보기


요약

추상 클래스, 인터페이스 공통/차이 정리 표

구분 추상 클래스 인터페이스
공통점 객체 생성 객체를 생성(인스턴스화)할 수 없다.
추상 메서드 추상 메서드를 포함한다.
기능적 목적 상속받는 클래스에서는 추상 메서드를 반드시 재정의하여 구현해야 한다.
차이점 개념적 목적 상속 받아서 기능을 확장시키는데 목적 구현 객체의 동일한 실행 기능을 보장하기 위한 목적
클래스 클래스다.(abstract class) 클래스가 아니다.(interface)
일반 메서드 일반 메서드 정의가 가능 일반 메서드 정의 불가능
(Java8 이후 static, default 메서드 정의 가능)
멤버 변수 클래스와 동일하게 변수 선언 및 사용 가능 상수만 사용 가능
상속 키워드 extends implements
다중 상속 불가능 가능

왜 헷갈릴까?

추상 클래스와 인터페이스는 개념적으로나 사용하는 목적에 있어 비슷한 부분이 많아..

처음 해당 내용에 대해 배우는 학생이나 실무에서 개발을 하고있는 개발자들도 자주 혼란(?)을 겪을 수 있는 주제이다.

 

둘 모두 *추상 메서드라는 내용에 대한 구현이 없는 선언부만 가지고 있는 메서드를 가지고있으며, *독립적으로 객체를 생성할 수 없다는 공통점이 있습니다.

사용하는 목적에 있어서도 추상 클래스나 인터페이스 모두 여러 곳에서 사용될 공통된 기능에 대한 구현을 강제하기 위한 기능을 하고있습니다.

 

*추상 메서드: 구현부 없이 선언부만 가지고 있는 멤버 메서드

abstract class Animal {
	// 숨쉬기(일반 메서드(선언부 + 구현부 존재)
	void breath() {
		System.out.println("숨쉬기");
	}

	// 울음소리(추상 메서드(선언부만 존재)
	abstract void cry();
}

interface Flyable {
	// 날기(추상 메서드(선언부만 존재)
	void fly();
}


*독립적으로 객체를 생성할 수 없다

Animal animal = new Animal(); // ERROR, 'Animal' is abstract; cannot be instantiated
Flyable flyable = new Flyable(); // ERROR, 'Flyable' is abstract; cannot be instantiated

위와 같은 내용으로 추상클래스나 인터페이스를 객체 생성(인스턴스화) 하려고 소스를 작성하면,

'OOO' is abstract; cannot be instantiated. << 다음과 같은 에러를 만날 수 있다.

('OOO'은 추상적이다. 인스턴스화 할 수 없다.)

 

그렇다면, 차이점은?

헷갈리지 않기 위해 차이점을 알아보자

추상 클래스는 extends, 인터페이스는 implements라는 상속 키워드를 사용한다.

각 단어의 뜻을 사전에서 찾아보면 다음과 같다.

 

extends: 확대[확장] 하다

implements: 시행하다, 실행하다

 

개념적 차이점이 아닌 실제 적용하는 것에서 차이점을 생각해보면,
추상 클래스extends(기능 확장의 느낌) 키워드 그대로 자신의 기능들을 하위로 확장시키는 것으로 볼 수 있습니다.
인터페이스implements(실행하는 기능 구현의 느낌) 키워드처럼 인터페이스에 정의된 메서드를 각 클래스의 목적에 맞게 동일한 기능으로 구현하는 것으로 볼 수 있습니다.

또 다른 관점에서는 추상 클래스는 이를 상속할 각 객체들의 공통점을 찾아 추상화시켜놓은 것으로 상속 관계를 타고 올라갔을 때, 같은 부모 클래스를 상속하며, 부모 클래스가 가진 기능들을 구현해야 하는 경우에 사용합니다.
반면 인터페이스는 상속 관계를 타고 올라갔을 때, 다른 부모 클래스를 상속하더라도 같은 기능이 필요한 경우에 사용됩니다.


추상 클래스(Abstract Class)

class 앞에 'abstract' 키워드를 사용하여 정의하며, 하나 이상의 추상 메서드를 가지는 클래스를 말합니다. 추상 메서드를 선언하여 상속을 통해서 하위 클래스에서 (반드시) 구현하도록 강제하는 클래스

추상 클래스는 하나 이상의 추상 메서드 가지고 있는 클래스를 말하며, 추상 메서드를 포함하고 있다는 점을 제외하면 일반 클래스와 모든 점이 동일하다.(생성자, 필드(멤버 변수), 일반 메서드(멤버 메서드) 포함 가능)

 

  • 추상 클래스는 인스턴스, 즉 객체를 만들 수 없는 클래스 입니다.(new 키워드로 객체 생성 불가(new 추상클래스() X))
  • 추상 클래스는 상속 키워드로 extends를 사용합니다.(일반 클래스 상속과 동일)
  • 추상 메소드는 (추상 클래스를 상속 받는)하위 클래스에서 메소드의 구현을 강제해야 합니다.(Override)
  • 추상 메소드를 포함하는 클래스는 반드시 추상 클래스여야 합니다.
  • 다중 상속이 불가능합니다.

인터페이스(Interface)

'interface' 키워들르 사용하여 정의하며, 오직 추상 메서드상수(static final)만을 가지고 있는 것을 인터페이스라고 한다. 추상 클래스와 마찬가지로 인터페이스 또한 인터페이스의 선언되어있는 추상 메서드를 implements 하는 클래스에서 (반드시) 구현하도록 강제한다.

  • 인터페이스의 모든 멤버 변수는 public static final 이어야 하며, 이를 생략할 수 있습니다.
  • 인터페이스의 모든 메서드는 public abstract 이어야 하며, 이를 생략할 수 있습니다.
  • Java 8 부터는 static, default method를 사용할 수 있습니다.
  • 인터페이스는 상속 키워드로 implements를 사용합니다.
  • 다중 상속이 가능합니다.

다중 상속?

하나의 하위 클래스에서 여러 상위 클래스를 상속 받는 것

- java는 다중 상속을 지원하지 않는다. 왜?

class Car {
	public void drive() {
		System.out.println("차를 운전하다");
    }
}

class Ship {
	public void drive() {
		System.out.println("배를 운전하다");
    }
}

// 다중 상속 가정 코드(실제로는 아래 코드 에러남)
class MyVehicle extends Car, Ship {
	// ...
}

위와 같이 Car(차)와 Ship(배) 클래스를 동시에 상속 받는 MyVehicle라는 클래스가 있다고 가정한다면, MyVehicle을 인스턴스화 하여 drive() 메서드를 호출하는 경우 문제가 발생합니다. Car와 Ship의 둘 다 동일한 drive() 멤버 메서드가 존재하는데... 어떤 메서드를 실행할까요? 이 내용이 다중 상속의 모호성에 대한 내용입니다.

이러한 다중 상속시 발생가능한 모호성 때문에 java에서는 다중 상속을 지원하지 않고 있습니다.

 

그러나, 인터페이스의 경우 아래와 같이 다중 상속 구현이 가능한데요

interface Runnable {
	void action();
}

interface Flyable {
	void action();
}

class Bird implements Runnable, Flyable {
	@Override
	void action() {
		// todo
	}
}

 

implements 하는 인터페이스의 경우에는 모든 멤버 메서드가 추상 메서드이기 때문에 동일한 이름의 action()이라는 메서드가 있어도, 상속 받는 클래스에서 재정의(오버라이딩)을 해서 사용하기 때문에 위에서 언급한 다중 상속의 모호성 문제가 발생하지 않습니다.