# 추상 클래스와 인터페이스 ## 추상화 (abstract) - 객체지향의 4대 특성 중 하나 - 정의 - 공통적인 특성을 추출하는 것 - 예시 - 아우디, 벤츠, BMW 클래스가 있다면, 자동차라는 추상 클래스를 만들고 공통적인 특성을 추출해서 자동차 클래스에 정의한다. ## 추상 클래스 - 추상 클래스는 인스턴스를 생성할 수 없음 - 일반적으로 하나 이상의 추상 메서드를 포함 - 공통된 로직은 추상 클래스에 작성하고, 각각의 구현 클래스에서 달라져야하는 부분만 추상 메서드를 오버라이딩해서 다르게 작성할 수 있다. ```java public abstract class AbstractClass { public void implementedMethod() { System.out.println("AbstractClass implementedMethod"); this.abstractMethod(); } abstract public void abstractMethod(); } public class ExtendedClass extends AbstractClass { @Override public void abstractMethod() { System.out.println("ExtendedClass abstractMethod"); } } ``` ### 추상 클래스는 인스턴스를 정말 생성할 수 없을까? - 방법이 있긴 하다. - new 키워드로 인스턴스 생성 -> 추상 메서드 구현 ```java public class AbstractClassExampleMain { public static void main(String[] args) { AbstractClass abstractClass = new AbstractClass() { @Override public void abstractMethod() { // 이렇게 사용하려면 여기서 추상 메서드를 구현해야함 System.out.println("AbstractClass abstractMethod"); } }; abstractClass.implementedMethod(); abstractClass.abstractMethod(); AbstractClass extendedClass = new ExtendedClass(); extendedClass.abstractMethod(); // Q. 바로 위에 있는 abstractClass 를 호출하는 걸까? 아니면 ExtendedClass 의 abstractMethod 를 호출하는 걸까? -> 실제 들어있는 인스턴스가 ExtendedClass 이기 때문에 ExtendedClass 클래스의 메서드를 호출한다. } } ``` - **Q. ExtendedClass의 인스턴스를 어떻게 AbstractClass의 참조형 타입(레퍼런스 타입)인 extendedClass에 넣을 수 있을까?** - **Q. 클래스와 인터페이스의 차이점은?** ## 인터페이스 - 클래스는 하나만 상속받을 수 있지만 인터페이스는 여러 개 구현할 수 있음 - implements한 인터페이스를 반드시 구현해야 함 ```java public class ImplementsClass implements SomeInterface, AnotherInterface { @Override public void someMethod() { System.out.println("ImplementsClass someMethod"); } @Override public void anotherMethod() { System.out.println("ImplementsClass anotherMethod"); } } ``` #### default 메서드? - 인터페이스에 메서드 정의 기능 ```java public interface SomeInterface { void someMethod(); // 추상 클래스에서 이미 정의된 추상 메서드를 호출하는 것과 동일하다. default void defaultMethod() { // 인터페이스에 메서드 정의 가능 this.someMethod(); // 정의되지 않은 메서드도 호출 가능 } } public class InterfaceExampleMain { public static void main(String[] args) { SomeInterface someInterface = new ImplementsClass(); someInterface.defaultMethod(); } } ``` ### 추상 클래스 vs 인터페이스 default 메서드 - 자바 8버전부터 인터페이스에도 default 메서드를 통해 메서드를 정의할 수 있는 기능이 추가됐다. - 일반적으로 추상클래스를 사용해야만 하는 상황이 아니라면 인터페이스의 defualt 메서드를 사용하는 게 낫다. 왜냐하면 추상클래스보다 인터페이스가 더 추상적인 존재이기 때문 ### Q. 추상 클래스를 사용해야만 하는 상황은? - 인스턴스 변수(필드)가 필요한 경우 - 생성자가 필요한 경우 - Object 클래스의 메서드를 오버라이딩 하고 싶은 경우 ## default 메서드 - **Q. 왜 등장했을까?** - 만약 인터페이스에 새로운 메서드를 추가한 상황에서 그 인터페이스를 구현한 구현체가 100개라면? 100개의 구현체에 모두 새롭게 추가된 메서드를 구현해야한다. - 기존의 구현을 고치지 않으면서 이미 공개된 인터페이스를 변경하기 위해 default 메서드가 등장했다. ### 동작원리 - 구현체가 로드될 때 인터페이스에 default 키워드가 붙어있는 메서드가 로드되면서 컴파일 시에도 아무 문제없이 실행이 가능하다. -> 기존의 코드를 최대한 수정하지 않으면서 설계된 인터페이스에 새로운 확장을 가능케 한다. ```java public interface List<E> extends Collection<E> { /// .... default void sort(Comparator<? super E> c) { Object[] a = this.toArray(); Arrays.sort(a, (Comparator) c); ListIterator<E> i = this.listIterator(); for (Object e : a) { i.next(); i.set((E) e); } } ```