본문 바로가기
JAVA/[JAVA] Techs & Rules

[JAVA] 추상클래스와 인터페이스(abstract class & interface)

by AndrewL 2020. 10. 3.

[JAVA] 추상클래스와 인터페이스(abstract class & interface) 

자바의 상속 개념을 사용할 때, 헷갈리는 개념에 대해서 정리해보려 한다.

조금 자세히 추상클래스와 인터페이스의 외향적인 차이와 다형성, 존재 이유에 대해서 살펴보겠다.

 

상속의 개념

상속이라는 개념은 어느 객체에서 공통된 기능이나 그 기능을 포함하는 다른 객체를 만들거나 할 때, 유용하게 그 기능을 사용하기 위해서 만들어진 개념이다.

예를 들어, 어벤져스의 인원들에 대한 설명을 프로그래밍한다고 생각해보자. 어벤져스의 공통적인 특성인 1. 슈퍼히어로이다 2. 평범하지 않은 과거를 가지고 있다  등 이런 공통적인 특성들이 있을것이고 차별되는 각각의 특성들인 1. 하늘을 날 수 있다. 2. 힘이 매우 쎄다(헐크) 등 많은 특징을 설명할 수 있을 것이다. 그런데 각각의 한명한명 공통적인 특성을 모두 나열하기 보다 어벤져스의 특성을 모두 적고, '토르' extends '어벤져스'를 하면 더 편리하게 프로그래밍 할 수 있을 것이다. 그래서 상속이라는 개념을 사용한다.


추상클래스와, 인터페이스의 기본 구조

//추상클래스(abstract Class) 예시
abstract class Avengers
{
 abstract void fight(); //메소드 앞에 abstract가 있으면 추상클래스이다.
 void hit(int x)
 {
  x=3;
 }
}
//인터페이스(interface) 예시
interface Avengers
{
 void fight(); //인터페이스에서는 abstract생략 가능하다.
 abstract void protect();
}

-> 추상클래스 abstract를 class 앞에 명시하여 표현, 인터페이스 interface를 인터페이스명 앞에 명시하여 표현한다.


추상클래스와 인터페이스의 역할/특징

 

그러면 , 추상클래스와 인터페이스(abstracts, interface)는 상속받는 클래스 혹은 구현하는 인터페이스 안에 있는 추상 메소드를 구현하도록 강제하는 것이다. 결국 둘 다 비슷한 일을 하는 것이라고 느껴진다. 

 

 

그런데, 추상클래스 하나를 두고, 각각 껍데기(추상 메소드)들만 두고  상속받는 객체에서 구현(오버라이드)하면 되는데 왜 인터페이스라는 개념을 사용할까?

 

답은 자바가 다중 상속을 지원하지 않기 때문이다.

 

다중 상속이라는 것은 super class(부모 클래스)를 2개 이상 두는 것이다. 예를 들어서

//다중 상속
class Futurecar extends Car, Plane
{
 @Override
 public void move()
 {
  super.drive();
 }
}

-> 다음과 같은 코드에서 car, plane 클래스 모두 move()라는 메소드를 가지고 있다면, 어떤 메소드가 사용될 지 모호하다. 이 다중 상속의 모호성 때문에 자바에서는 다중 상속을 금지한다.

 

하지만, 인터페이스는 아래와 같이 여러개의 인터페이스를 구현할 수 있다.

class Car implements vehicle, engine
{
 @Override
 public void drive()
 {
  @doSomething
 }
}

▶특징 1

implements의 가장 큰 특징은 부모의 메소드를 반드시 모두 오버라이딩해야 한다.

 

정리하면, extends : 클래스를 확장하는 것이고, implements :  인터페이스를 구현하는 것이다.

 

▶특징 2

추상 클래스든 인터페이스이든 상속받기로 하였으면 안에 있는 추상 메소드는 전부 구현해 주어야 한다. 그러나 추상 클래스가 추상 클래스를 상속받는다면, 추상 메소드를 꼭 구현할 필요는 없고 다른 추상 메소드를 만들어도 상관없다.

 

▶특징 3

접근 지정자를 public모드로 쓴 이유?

-어떤 상황에서든 해당 멤버들을 반드시 구현해야 하므로 관련 메소드에 아무런 제약없이 접근할 수 있어야 하기 때문이다. 


추상클래스와 인터페이스를 상속받는 구조

 

위의 Avengers추상클래스와 Avengers인터페이스가 각각 어떤 방법으로 상속되는지 살펴보면,

class Thor extends Avengers
{
 void fight() //추상메소드였던 fight()는이렇게 일반 메소드형태로 전부 구현해 줘야 한다.
 {
  System.out.println("번개");
 }
 //hit()는 일반 메소드였으므로, 필요시 재정의하고 아니면 상속이니 있는 것으로 간주.
}

class Thor implements Avengers
{
 public void fight() //이렇게 일반 메소드 형태로 전부 구현해줘야 한다.
 {
  System.out.println("번개");
 }
 public void protect() //접근 지정자를 완화시켜 public 으로 구현해준다.
 {
  System.out.println("인류를 지킨다.");
 }
 }

-> 처음 코드 예제의 추상클래스와 인터페이스 구조에서 살펴봤듯이, Avengers추상클래스와 인터페이스를 상속받을 때,

 

1. 추상클래스를 상속받을 때는 추상메소드였던 fight()부분만 구현해주고, hit()는 구현되어 있는 일반 메소드이므로 필요시 재정의하고 있는 것으로 간주한다.

 

2. 인터페이스를 상속받을 때는 둘 다 추상 메소드로 껍데기만 있으므로 모두 구현해 주었다.


 

어떤 상황에서 많이 사용될 까? 유용한 점이 무엇일까?

 

추상클래스

1. 같은 종류나 행동들을 구현할게 많을 때 쓰고,

2. 상속에 대한 계층구조를 명확히 표현할때 추상클래스를 이용.

3. 일반변수들과 일반 메소드들도 쓸 수 있고 아직 구현하지 않아도 될 메소드는 그냥 내버려 둘 수 있어 상황에 따라 편리하다.

 

인터페이스

1. 디자인을 구성하는 요소들이 자주 바뀔 때 (Update)

2. 메소드 형태만 서로 공유해서 구현되는 상황일 때 (Share)

3. 클래스 전체가 아닌 메소드들만 쓰고 싶을 때

 

좀 더 깊이 들어가자면 인터페이스의 사용빈도가 상당히 높은 데 그 이유 중 하나가 동시개발이 가능하므로 시간을 많이 단축시킬 수 있다는 점이다.

 

인터페이스 안의 메소드들은  내용이 없는 상태이나 메소드에 대한 결과값은 내용을 만들지 않아도 미리 알수 있으므로 인터페이스의 내용을 누군가가 구현하고 있는 동안에 다른 한사람은 그 메소드가 구현되고나면 작동할 결과값으로 같은 시간에 다른 일을 할수 있으니 개발작업이 한층더 빨라질수 있는 것이다.

 

또한 여러사람이 인터페이스를 통해 그런 작업을 동시에 한다고 가정했을때 인터페이스안의 메소드 내용을 변경하더라도 그와 관련된 모든 클래스들을 변경할 필요없이 해당 메소드의 구현되는 내용만 변경하면 모든 처리가 가능해지므로 매우 유용하다.

 

 

댓글