인터페이스는 객체가 수행할 행위를 정의하는 구조다. 클래스처럼 구현 방식이 아닌 어떤 기능을 제공해야 하는지 명시하는 것이 목적이다. 즉, 인터페이스는 ‘어떻게’가 아닌 ‘무엇’을 정의한다.
static final 필드 가능)public interface Logger {
default void log(String msg) {
System.out.println(msg);
}
} 인터페이스에서도 일부 구현이 가능해졌다.Payment pay = new KakaoPayment();
Payment pay = new NaverPayment(); 인터페이스를 사용하면 구현체가 아닌 추상 타입에 의존하게 된다. 이를 통해 구현체가 변경 되더라도 사용하는 코드의 영향을 최소화할 수 있다.public interface Flyable {
public abstract void fly();
}
public interface Runnable {
void run();
}
public interface Swimable {
void swim();
}
public class Bird implements Flyable, Runnable{
@Override
public void fly() {
System.out.println("Bird flies");
}
@Override
public void run() {
System.out.println("Bird runs");
}
}
public class Fish implements Swimable{
@Override
public void swim() {
System.out.println("Fish swims");
}
}
예시처럼 인터페이스는 특정 객체가 수행해야 하는 행위를 정의하는데 적합하다. 기본적으로 선언하는 메소드는 public abstract 이기 때문에 생략이 가능하다. implements 키워드를 통해 구현을 할 수 있다.
추상 클래스는 일부 구현을 제공하면서, 하위 클래스에게 특정 동작을 구현하도록 강제하는 클래스다. 인터페이스는 ‘무엇’을 정의 했다면, 추상 클래스는 기본 동작은 제공하면서 확장된 구조를 만드는데 목적이 있다.
abstract class Animal {
protected String name;
public Animal(String name) {
this.name = name;
}
abstract void sound();
void eat() {
System.out.println(name + " eats food");
}
}
class Dog extends Animal {
public Dog(String name) {
super(name);
}
@Override
void sound() {
System.out.println("Woof");
}
}
class Cat extends Animal {
public Cat(String name) {
super(name);
}
@Override
void sound() {
System.out.println("Meow");
}
}
추상 클래스는 확장된 구조를 갖는데 목적이 있다. 예시를 보면, 공통된 로직은 기본 메서드로 제공하지만, 특정 객체에 따라 달리 동작할 수 있는 부분을 추상 메서드로 제공해 확장성을 높여준다.