추상 클래스는 완전하게 구현되어있지 않은 메소드를 가지고 있는 클래스를 의미한다. 메소드가 미완성되어 있으므로 추상 클래스로는 객체를 생성할 수 없다. 추상 클래스는 객체를 만들려고 하는 게 아니라, 상속 받는 다른 클래스를 만드는게 목적임.
예를 들면 동물을 Animal class로 정의할 때, 구체적으로 어떤 동물이 오게 될지 알 수 없음. 그래서 구체적인 동작을 구현하긴 어렵다. 동물이 움직인다는 건 알지만, 날아다닐지 뛰어다닐지 기어다닐지 알 수 없다. 그래서 Animal class의 move()라는 메소드를 처음부터 완전하게 작성할 수가 없기 때문에, Animal을 추상 클래스로 정의하는 것.
자바에서 추상 클래스를 만들기 위해서는 클래스 선언시 앞에 abstract를 붙인다.
추상 클래스는 하나 이상의 추상 메소드를 가지고 있어야한다. 추상 메소드란 move()처럼 몸체가 없는 메소드를 말한다. 각종 동물들의 움직이는 방법은 동물에 따라 다르고, 어떤 동물이 오게 될지 모르니까 추상 메소드로 선언하는 게 논리적이다.
추상 클래스를 상속받는 자식 클래스에서는 반드시 추상 메소드를 재정의하여야 한다. 재정의하지 않으면 오류가 생김.
public abstract class Animal {
public abstract void move(); // 추상 클래스라 move의 바디가 없음.
}
public class Lion extends Animal {
public void move(){
System.out.println("어흥");
}
public class Lion extends Animal {
public void move(){
System.out.println("어흥");
}
=> 추상 클래스를 상속받는 자식 클래스에서는 반드시 추상 메소드를 재정의해줘야함. 그래서 Lion 클래스(자식 클래스)에서 추상 메소드(move)를 재정의(move() {System.out~})해줬다.
부모 클래스에서 바디가 없는 일반 메소드로 정의한 후에, 자식 클래스에서 재정의하는 것과, 추상 메소드를 사용하는 방법에는 어떤 차이가 있을까?
코드 짜보면 결과는 같다. 하지만 추상 메소드로 정의하면 자식 클래스에서는 반드시 구현해야 하므로, 구현을 강요하는 면에서 장점이 있다. 추상 메소드가 아니면 자식 클래스에서 재정의하지 않고 넘어가도 컴파일러가 체크할 수 있는 방법이 없음.