본문 바로가기

Project

자바의 추상클래스(Abstract class)와 인터페이스(interface class)


 사실 처음 자바를 공부하면서 궁금해 하던게 있었습니다.
그것은 추상클래스(Abstract class)와 인터페이스(Interface)의 차이 및 존재이유입니다.
 클래스는 크게 일반클래스와 추상클래스로 나뉘는데 추상클래스는 본문중에 '추상메소드'가 하나 이상 포함되는 경우를 말합니다. 인터페이스는 모든 메소드가 추상메소드인 경우 선언하는 경우가 많습니다.

추상메소드라 함은 메소드의 선언부만 있고 본문이 없는 것을 말합니다. 여기서 본문은 중괄호({})로 묶여진 몸체(body)부분을 말하는데 중괄호 안이 비어있더라도 이것이 존재한다면 그것은 추상메소드가 아닙니다. 추상메소드의 선언의 예는 다음과 같습니다.

abstract public void test( int a );

즉, 메소드의 선언 후에 세미콜른(;)만을 찍어 이를 선언만 하고 구현은 자식클래스에서 하게 하는 방법입니다. 일반 클래스의 경우 상속받은 자식클래스가 반드시 부모클래스의 메소드를 '오버라이딩(overriding)'할 필요가 없지만 추상클래스를 상속받은 자식클래스는 반드시 추상메소드를 오버라이딩하여야 하기에 메소드를 강제로 구현하게 할 때 많이 쓰입니다.
 추상클래스는 위에서 말한것처럼 추상메소드(빈메소드)를 선언하여 상속받아 쓰이는 모든 클래스에게
기능의 구현을 강제할때 쓰입니다.
 추상클래스와 인터페이스의 가장 큰 차이점은 바로 '클래스'냐 아니냐의 차이입니다. 추상클래스는 엄연한 클래스로 이를 구현하는 것은 '상속(extends)'입니다. 그러나 인터페이스는 '포함(implements)'라는 키워드를 통해 구현하게 되는데 이는 자바에서 매우 중요한 차이를 가집니다.

자바는 오로지 '단일 상속'만을 지원하기 때문에 추상클래스를 상속받는 클래스는 다른 클래스를 상속받을 수 없습니다. 그러나 인터페이스를 포함하는 클래스는 다른 클래스를 상속받을 수 있습니다.

추상클래스는 일반클래스와 달리 그 자신을 new 명령어를 통해 객체를 생성할 수 없습니다. 그러나 '다형성(polymorlphism)'을 통해 자식 클래스의 객체를 생성할 수는 있습니다.

인터페이스를 쓰는 가장 큰 이유는 다중상속을 지원하지 않는 자바에서 다중상속의 장점을 가져오기 위해서입니다. 다중상속이 가지는 단점은 배제하고 오직 장점만을 취하기 위해 인터페이스를 쓰는 것입니다.

상속이란 개념은 부모클래스의 속성과 메소드를 자식클래스가 물려받는다는 것인데 쉽게 예를 들면 '자동차'라는 클래스는 '색깔', '배기량' 등의 속성과 '기름을 넣는다', '달린다' 등의 메소드를 가질 수 있습니다. 이 클래스를 상속하는 '승용차' 클래스는 별도로 선언하지 않아도 부모클래스의 '색깔', '배기량'이라는 속성과 '기름을 넣는다', '달린다'라는 메소드를 가지게 되죠.

추상클래스는 이 부모클래스가 단순히 관념적인 성격이 강할 때 많이 쓰이는데 예컨데 '새'라는 클래스는 그냥 '난다'라는 메소드를 가지지만 새의 종류에 따라 나는 방법이 조금씩 틀려 자식클래스에서 어차피 구현해야 될 부분이므로 굳이 부모클래스에서 그 내용을 구현할 필요가 없기때문입니다.

 인터페이스는 추상 메소드만으로 이루어진 클래스를 말합니다.

 이 클래스는 추상클래스와 같이 객체를 생성하지 못합니다. 즉 상속받아 사용하거나 구현(Implement)하여
다른클래스에게 자신의 책임을 위임하지 않으면 안됩니다.

 이러한 클래스는 처음 보았을때 사못 비어있는 인터페이스를 상속받아야할 이유가 무엇일까 생각해봅니다.
구현해야할 제약을 의미한다면 추상클래스(Abstract class)에서 모든 메소드를 추상메소드로 구현하더라도
같은 의미가 아닐까요?

 보통 인터페이스를 사용하는 이유로서 다중상속을 통해 벌어지는 문제점을 해결하기 위해서이다.
라고 말을 하지만 왜 다중상속을 해야합니까? 라고 질문을 한다면 어떨까요?
 특히나 인터프리터 언어라든지 C++등의 언어는 다중상속을 문제없이 지원합니다. 또는 인터페이스라는
개념이 없지요.

 구현적인 관점에서 제가 생각하는 다중상속의 해야하는 이유 및 인터페이스를 사용해야하는 이유는

 자바로서 객체 지향을 구현하기 위해서는 먼저 아래의 2가지 특징을 이해하지 않으면 안됩니다.

    1. 자바는 Type기반 언어이기 때문에 자바의 상속은 형의 상속입니다.
    2. 자바는 같은 클래스의 형(상속관계)으로서만 캐스팅이 가능합니다.

 객체지향의 다형성(polymorphism)을 구현하는 방법은 각각의 언어마다 틀린데 자바는 위에서
보듯 객체를 호출할때 먼저 객체의 타입을 정해주지 않으면 안됩니다.
 즉 실제 호출하려는 함수는 원하는 함수가 들어있는 클래스 또는 인터페이스를 상속하지 않으면
안됩니다. 또 추상클래스 또는 인터페이스를 상속한 클래스는 추상메소드를 구현하지 않으면 안됩니다.
하지만 자바는 상속을 통해 일어나는 생성자와 소멸자,오버라이딩 등의 문제를 해결하기 위해서
상속을 사용하지 않고 되도록이면 구성(Composition)을 이용하도록 합니다.
 그리고 공통적인 인터페이스로 특정 지을수 있는 클래스들은 인터페이스를 상속함으로서
결함도를 줄일수 있습니다.

 마지막으로 정리하자면
1. 상속을 통한 제약을 이용해 자바는 다형성을 구현한다.
2. 다중상속은 여러 문제점이 있기에 제거하고 부족한 다형성은 인터페이스를 이용해 해결한다.

좀더 전문적인 용어가 있었군요.
상속은 서브클래싱을 의미하고 구현(implementation)은 서브타이핑을 의미합니다.

서브 클래싱은 상속을 통해 기능을 구현하는것을 말하고
서브 타이핑은 기능을 공통적인 타입으로 묶어주는것을 의미합니다.

서브클래싱,서브타이핑에 관한 참고자료 : 자바서비스넷