새로운 동물이 추가 되었을 때 변하는 부분을 최소화 하는 것이 잘 작성된 코드이다.
코드에서 변하는 부분과 변하지 않는 부분을 명확하게 구분하는 것이 좋다.
변경 범위가 많을 경우 코드가 지저분 해진다.
동물(Animal)과 같이 부모 클래스는 제공하지만, 실제 생성되면 안되는 클래스를 추상 클래스라 한다.
추상적인 개념을 제공하는 클래스이다. 실체인 인스턴스가 존재하지 않는다. 대신에 상속을 목적으로 사용되고, 부모 클래스 역할을 담당한다.
abstract calss AbstractAnimal {...}
부모 클래스를 상속 받는 자식 클래스가 반드시 오버라이딩 해야 하는 메서드를 부모 클래스에 정의할 수 있다. 이것을 추상 메서드라 한다. 추상 메서드는 이름 그대로 추상적인 개념을 제동하는 메서드이다. 따라서 실체가 존재하지 않고, 메서드 바디가 없다.
public abstract void sound();
추상 메서드가 하나라도 있는 클래스는 추상 클래스로 선언해야 한다.
추상 메서드는 메서드 바디가 없다. 따라서 작동하지 않는 메서드를 가진 불완전한 클래스이다.
따라서 직접 생성하지 못하도록 추상 클래스로 선언해야 한다.
추상 메서드는 상속 받는 자식 클래스가 반드시 오버라이딩 해서 사용해야 한다.
추상 메서드는 자식 클래스가 반드시 오버라이딩 해야 하기 때문에 메서드 바디 부분이 없다.
바디 부분을 만들면 컴파일 오류가 발생한다.
오버라이딩 하지 않으면 자식도 추상 클래스가 되어야 한다.
추상 메서드는 기존 메서드와 완전히 같다. 다만 메서드 바디가 없고, 자식 클래스가 해당 메서드를 반드시 오버라이딩 해야 한다는 제약이 추가된 것이다.
오버라이딩 하지 않을 경우
public abstract class AbstractAnimal처럼 abstract를 사용해야 한다.
public abstract class AbstractAnimal {
public abstract void sound();
// 추상 메서드는 자식 클래스가 반드시 오버라이딩 해야 한다.
}
public class HelloAnimal extends AbstractAnimal{
@Override
public void sound() {
// 오버라이딩 해야 한다. 오버라이딩을 하면 상관 없지만
}
}
추상 클래스는 제약이 추가된 클래스이다. 메모리 구조, 실행 결과 모두 동일하다.
추상 클래스 덕분에 실수로 Animal 인스턴스를 생성할 문제를 방지해준다.
추상 메서드를 사용하여 새로운 동물의 자식 클래스를 만들 때 실수로 sound()를 오버라이딩 하지 않을 문제를 방지해준다.
public abstract class AbstractAnimal {
public abstract void sound();
public abstract void move();
}
자바는 순수 추상 클래스를 더 편리하게 사용할 수 있는 인터페이스라는 기능을 제공한다.
인터페이스는 구현이다. 상속이라 하지 않고, 구현이라고 한다.
public abstract class AbstractAnimal {
public abstract void sound();
public abstract void move();
}
public interface InterfaceAnimal {
public abstract void sound();
public abstract void move();
}
public interface InterfaceAnimal {
void sound();
void move();
}
public class Dog implements InterfaceAnimal{
@Override
public void sound() {
System.out.println("멍멍");
}
@Override
public void move() {
System.out.println("개 이동");
}
}
인터페이스는 순수 추상 클래스와 같다. 약간의 편의 기능이 추가된다.
public interface InterfaceAnimal {
public static final int MY_PI = 3.14;
// int MY_PI = 3.14;로 주로 사용한다.
}
인터페이스에서 멤버 변수는 public, static, final 이 모두 포함되어 있다고 간주한다.
상수 정도는 정의할 수 있다.
인터페이스 구현(상속)이 된다.
인터페이스를 상속 받을 때는 implements를 사용한다.
public class Dog implements InterfaceAnimal {
}
클래스, 추상 클래스, 인터페이스는 모두 똑같다.
부모 클래스의 기능을 자식 클래스가 상속 받을 때 클래스는 상속 받는다고 하지만, 인터페이스를 구현한다고 표현하면 된다. 사실 자바에서는 상속과 구현은 똑같다. 동일하게 작동한다.
모든 메서드가 추상 메서드인 경우 순수 추상 클래스를 만들어도 되고, 인터페이스를 만들어도 된다. 인터페이스를 굳이 사용하는 이유가 있다.
제약 : 인터페이스를 만드는 이유는 구현하는 곳에서 인터페이스의 메서드를 반드시 구현하라는 규약을 주는 것이다.
다중 구현 : 자바에서 클래스 상속은 부모를 하나만 지정할 수 있다. 반면에 인터페이스는 부모를 여러명 두는 다중 구현(다중 상속)이 가능하다.
추상클래스는 추가된 기능을 자식 클래스에서 구현하지 않을 수 있다.
public abstract class AbstractAnimal {
public abstract void sound();
// 추상 메서드는 자식 클래스가 반드시 오버라이딩 해야 한다.
public abstract void move();// 모든 것이 다 추상 메서드가 된다.
public void hello() {
System.out.println("안녕하세요. 동물입니다.");
}
}
하지만 인터페이스는 모든 메서드가 추상 메서드이다.