-
Abstract Class와 Interface의 차이Java 2021. 4. 13. 18:53
개요
Java에서 상속을 받기 위해서는 두 가지 방법이 있는데요, 하나는 Abstract Class, 또 다른 하나는 Interface입니다.
하지만, 이 둘의 차이를 명확히 구분하기가 어렵다고 생각합니다. 예전부터 이 둘의 차이와 언제 사용해야 하는지에 대해서 궁금했었는데, 이번 포스팅을 작성하면서 정리하려고 합니다. 이펙티브 자바에서도 이와 관련한 토픽들이 있으니 찾아보면 도움이 될 것 같네요.
Abstract Class와 Interface의 공통점
abstract class Animal { public abstract void attack(); public void move() { System.out.println("move!"); } }
interface Talkable { public void talk(); }
Abstract Class와 Interface는 모두 Instance를 생성할 수 없습니다. 즉, new 키워드를 통해 객체 생성이 불가능합니다.
이들은 상속(extend)이나 구현(implement) 하기 위해서 존재하고, 구현해야만 사용할 수 있는 abstract method를 가지고 있습니다.
Abstract Class와 Interface의 차이점
가장 명확한 차이는 단일 상속 여부입니다. 기본적으로 Java는 단일 상속을 지원합니다. 말 그대로, 단 하나의 부모 클래스만을 가질 수 있다는 것입니다. 단일 상속만을 허용하는 이유는 다형성의 모호함을 제거하기 위해서입니다.
class Student extends Programmer, Engineer { @Override public void work() { System.out.println("do Work!"); } }
위의 예제처럼 여러 부모 클래스를 상속받는다고 가정합시다. Programmer와 Engineer 모두 work라는 abstract method를 가지고 있을 때, Student는 어떤 부모 클래스의 work를 상속받고 실행시켜야 할까요? 이러한 상황을 방지하기 위해 Java는 단일 상속만을 허용합니다.
이러한 차이 외에 중요한 점으로 다른 블로그에서도 많이 언급되는
Abstract Class는 Is-a이고, Interface는 Has-a 가 있습니다. 제가 이해한 방식은, Abstract Class는 부모 클래스의 기능을 사용, 확장하고, Interface는 Interface의 method 구현을 강제한다는 것입니다. Abstract Class를 상속받는 자식 클래스들은 공통된 메소드를 다시 재정의하지 않아도 되지만, Interface는 명시된 method를 모두 재정의가 필요합니다.
반면, 다른 Abstract Class를 상속받는 자식 클래스가 동일한 동작을 강제하려면 같은 Interface를 구현받으면 됩니다. 즉, Abstract Class를 사용하면 Class 간의 계층 구조와 구분이 명확해지고, Interface는 다른 Class들끼리 같은 동작을 하게 만드는 목적입니다.
위의 계층 구조를 보면, Carp와 Man은 각각 다른 부모 클래스를 상속받습니다. 하지만 두 클래스 모두 수영을 할 수 있는 클래스이기 때문에, Swimable Interface를 공통으로 구현하게 됩니다.
Abstract Class의 단점과 Composition
이펙티브 자바의 아이템 18 '상속보다는 컴포지션을 사용하라'는 상속(확장)의 단점을 명확히 보여줍니다. 가장 큰 단점은 상위 클래스의 메소드를 하위 클래스가 재정의할 때, 캡슐화를 유지할 수 없다는 것입니다. 참조하는 상위 클래스의 메소드가 내부적으로는 다르게 구현됐을 수도 있고, 하위 클래스에서 특정 메소드를 정의하고 이후에 상위 클래스에서 동일한 이름의 메소드를 추가하게 되면, 당연히 컴파일 에러가 발생합니다. 이는, 동일한 프로그래머가 상위, 하위 클래스를 운용한다면 큰 문제가 되지 않을 수 있겠지만, 거대한 시스템일수록 예상치 못한 문제가 생길 여지가 있습니다.
그래서, 이펙티브 자바에선 컴포지션 패턴을 추천합니다. 흔히 말하는 Wrapper Class가 컴포지션 패턴과 거의 같다고 보시면 될 것 같습니다. 컴포지션 패턴은 상위 클래스를 상속하는 대신, 새로운 클래스를 생성해서 상위 클래스의 인스턴스를 가지는 형태를 말합니다.
참고 사이트
'Java' 카테고리의 다른 글
Java의 Singleton Pattern에 대하여 (0) 2021.05.26 Java에서 동시성 관리 - Synchronization (0) 2020.12.29 Java GC와 Object간 Reference (0) 2020.10.18 Java로 구현하는 DFS 알고리즘 (0) 2020.02.24