객체 간의 공통적 특성을 추출한 클래스라고 생각하시면 되겠습니다. 예를 들자면 강아지, 고양이, 염소라는 객체가 있다고 해봅시다. 이 3가지 객체의 공통점은 동물이라는 공통점이 있습니다. 여기서 동물은 구체적인 실체라기보다는 "수명", "짖기"와 같은 필드와 메서드를 가지고 있는 모든 동물 객체들의 공통되는 특성을 갖고 있는 추상적인 클래스입니다.
변수, 메소드은 네이밍이 소스 가독성에 큰 영향을 줍니다. 명칭만으로도 용도를 추측할 수 있기 때문입니다. 이러한 변수와 메서드의 명칭은 각각의 클래스마다 최대한 통일을 시켜줘야 합니다. 그래야 "여기에도 이것이 있겠지" 하고 개발자가 원하는 부분을 방대한 소스 속에서 빠르게 찾아갈 수 있습니다. 예를 들어 동물이라는 추상 클래스에 "짖다"라는 메서드명이 각자 다르다고 생각해봅시다. 개 클래스에는 Bark(), 사자 클래스에는 Roar() 그리고 늑대 클래스에는 Howl()이라는 메서드명으로 각각 지정하였다고 합시다. 언뜻 보면 합리적인 선택으로 보입니다. 영어로 개는 짖을 때 Bark, 사자는 포효할 때 Roar, 늑대는 울 때 Howl이라고 하기 때문입니다. 하지만 이렇게 동일한 기능을 하는 메서드들을 다른 명칭들로 계속해서 작성하다 보면 소스의 가독성이 떨어집니다. 갈수록 코드가 중구난방이 되어버리겠죠. 그래서 장기적인 관점에서 동물이라는 추상 클래스에 Bark()라는 클래스명을 작성하고 그 추상 클래스의 Bark를 아래 객체들이 상속받는 형태로 네이밍을 통일하는 것이 좋습니다.
추상클래스추상 클래스 또한 객체이기 때문에 클래스를 상속하면서 누릴 수 있는 이점들을 추상 클래스도 그대로 누릴 수 있습니다. 예를 들어 많은 객체들을 생성할 때 모든 객체들에 공통적인 메서드와, 필드들을 추상 클래스로 만들고 이 추상 클래스를 하위 자식들이 상속받아 필요한 필드와 메서드를 그대로 상속하고 추상 클래스는 자식에서 재정의하는 방식을 통해 개발의 효율성을 증대시킬 수 있습니다.
자바에서 추상클래스를 선언할 때는 클래스 선언 시 abstract라는 키워드를 붙여서 만들면 됩니다. 단 이렇게 abstract라는 키워드를 붙여 추상 클래스로 만들게 되면 new 연산자를 사용하여 직접 객체를 만들지는 못하고 오직 상속을 통해 자식 클래스만 만드는 용도로만 사용이 가능합니다. 그리고 추상 클래스 내에 추상 메서드라는 메서드를 생성하실 수 있습니다. 이 메서드는 추상 클래스에서 껍데기만 생성하고 상속하는 자식 클래스에서 필수로 오버 라이딩하여 사용합니다.
public abstract class Car {
String name;
String company;
public Car(String name, String company) {
this.name = name;
this.company = company;
}
public void move() {System.out.println("이동한다");}
public void speedup() {System.out.println("가속한다.");}
public void speeddown() {System.out.println("감속한다.");}
public abstract void sound();
추상 클래스도 일반 클래스와 마찬가지로 필드, 생성자, 메서드를 선언하실 수 있으며 자식 객체가 생성될 때 super를 호출하므로 생성자는 반드시 있어야 합니다. 그리고 추상 클래스를 작성하다 보면 선언만 하고 상속받는 자식 클래스에서 메서드를 재정의하여 사용하여야 하는 경우들이 있습니다. 추상 메서드는 자식 클래스에서 오버라이드를 강제할 수 있기 때문입니다.