가장 간단히 말하면, abstract class는 abstract keyword를 사용해 선언된 class를 말한다. 이 class는 abstract 메소드를 가질 수도, 가지지 않을 수도 있다. JVM은 abstract class를 동작이 완전히 정의되지 않은 불완전한 class로 인식한다. class를 abstract로 정의하는 것은 오직 하나만을 강제한다 : 이 class의 instance를 생성할 수 없다는 것
abstract class TestAbstractClass
{
public abstract void abstractMethod();
public void normalMethod()
{
//method body
}
}
TestAbstractClass에는 두 개의 메소드가 있다. abstract 메소드와 일반 메소드. abstract 메소드를 포함한 class는 무조건 abstract class로 선언해야 한다.
abstract 메소드는 그 자리에서 바로 구현(implement)되지 않은 메소드이다. 어플리케이션에서 abstract 메소드를 사용하는 유일한 방법은 이 class를 extend하는 것이다. subclass가 superclass의 행동을 상속하고 superclass가 subclass에 대한 참조를 갖고 있을 수 있다는 점은 abstract class의 중요성을 높여준다.
java에서는 어떤 class든지 모든 interface를 implement할 수 있다는 규칙이 있기 때문에 interface 내에 정의된 모든 메소드는 public이어야 한다.
public interface TestInterface
{
void implementMe();
}
위의 interface를 implement하는 모든 class는 impleMentMe() 메소드를 override해야 한다.
interface를 implement하면서 그 내부의 메소드를 override하지 않는 경우는 다음이 유일하다 : implement하는 class를 abstract으로 정의하는 경우
public abstract class TestMain implements TestInterface
{
//No need to override implement Me
}
그 외의 경우에는 다음과 같이 무조건 implementMe() 메소드를 override 해야 한다.
public class TestMain implements TestInterface
{
@Override
public void implementMe() {
// TODO Auto-generated method stub
}
}
abstract class는 몇몇 행동들을 정의할 수 있게 해준다. HttpServlet의 예시를 보자. Servlet 기술을 사용하는 웹 어플리케이션을 개발하면 이 class는 늘 상속 받아야 한다. 각각의 servlet은 initialization, service, destruction의 life cycle 단계를 가진다. servlet을 만들 때마다 각각의 단계에 대한 코드를 새로 작성해야 하면 엄청난 낭비일 것이다.
JDK 디자이너들은 이를 해결하기 위해 HttpServlet abstract class를 만들었다. 여기엔 각각의 단계에 대한 기본 코드들이 이미 작성되어 있다. 여기서 필요한 메소드들만 override하면 손쉽게 사용할 수 있게 된다.
interface는 class의 특징만을 정의하고, 그 interface를 implement하는 class에게 그 특징들 모두를 하나하나 구현하도록 강제하고 싶을 때 사용하면 된다.
collection framework의 Map interface를 생각해보자. 여기서는 map이 어떻게 동작해야 하는지 규칙만을 정의할 뿐이다. 예를 들면 key-value 쌍을 저장해야 한다던가, value는 key를 통해 접근 가능해야 한다던가 하는 것들이다. 이러한 규칙은 interface 내에 abstract 메소드 형태로 정해져 있다.
이를 implement 하는 class들(HashMap, HashTable, TreeMap 등)은 interface 내의 method들을 서로 다르게 implement하고 그래서 나머지와 다른 특징들을 갖게 된다.
또한 interface는 책임의 분리를 정의하는 데 사용될 수 있다. 예를 들어, HashMap은 3개의 interface를 implement한다 : Map, Serializable, Cloneable. 각각의 interface는 분리된 책임을 정의하기 때문에 class가 필요한 interface들을 골라서 구현할 수가 있다.
제일 부모 class인 creature는 생물에 대한 정의를 내리고 있는 abstract class이다. 이를 상속 받는 Animal, Plant abstract class는 각각 동물, 식물의 특성을 abstract method로 정의한다.
여기서 interface의 사용 목적을 알 수 있는데, Eatable interface를 사용함으로써 Animal, Plant 즉 각각 다른 부모 class를 상속 받고 있는 Monkey, Kim 등의 class에게 공통적인 기능인 먹는 기능을 구현했다. 즉, 상속 관계가 다름에도 같은 기능을 implement하도록 강제할 수 있다.
위의 Talkable interface는 동일한 부모 class인 Animal을 상속 받는 Kim, Gil에서 사용하고 있는 기능이다. 그래서 아래와 같이 Human abstract class를 생성해서 Kim, Gil이 상속 받도록 하면 공통 기능(Talkable)의 구현을 강제할 수 있다.