Java

자바 [JAVA] - Interface와 Class

2nyong 2023. 3. 23. 14:16

이번 포스트에서는 Interface와 Class를 비교하여 간략히 정리한다.

 

앞선 포스트에서 Interface는 객체의 특정 행동의 특징을 정의하는 간단한 문법이라고 정리하였다. Class와 비교하자면 Interface는 메소드의 껍데기만 남겨둔 Class라고 볼 수 있다.

 


 

Interface와 Class 예시

예를 들자면, 지금 우리가 알고 있는 일반적인 자동차는 바퀴가 4개 있고, 핸들과 기어가 있으며 어떤 에너지를 활용해 움직일 수 있는 물체라는 개념이 존재한다. 이러한 추상적인 개념을 Interface라고 볼 수 있다.

public interface Car {

    void setWheel();
    void setHandle();
    void setGear();
    
    int energyType();
	
    //...//
}

 

그렇다면 Interface와 비교하여 Class는 어떻게 설명할 수 있을까? 자동차의 추상적인 개념들을 구체화(구현)하여 바퀴의 크기나 디자인, 또는 위치등을 구체적으로 설정해 제네시스 G90 등 하나의 특정한 자동차가 만들어 진다. 이를 Class라고 할 수 있다.

class G90 implements Car {

    @Override
    void setWheel() {
        wheelNum = 4;
    }
    
    @Override
    void setHandle(int size) {
        handleSize = size;
    }
    
    @Override
    void setGear(...) {
        //...//
    }
    
    @Override
    int energyType(...) {
        //...//
    }
}

 

일반화

이제 자동차에서 벗어나 일반화를 해보자. Interface는 표현하고자 하는 것에 대한 기본적인 필수요소를 선언만 해놓은 것이고, Class는 이런 요소들을 구체적으로 구현하는 것이다.

 

따라서 Interface에 선언된 메소드들이 있다면, 이 Interface를 구현하는 Class는 Interface에 선언된 메소드를 반드시 구체화 하도록 강제한다. 그리고 이것을 Override(오버라이드), 재정의라고 부른다.

 

또, Interface와 같이 메소드를 선언만 해놓을 뿐 그 내용을 구체화하지 않은 메소드를 일반적으로 추상 메소드라고 한다.

 


 

Interface의 static, defulat 메소드

그러나, Java 8 부터는 Interface에서도 일반 메소드를 구현할 수 있다. 

 

Comparator Interface 코드를 살펴보면

    default Comparator<T> thenComparingDouble(ToDoubleFunction<? super T> keyExtractor) {
        return thenComparing(comparingDouble(keyExtractor));
    }

    /**
     * Returns a comparator that imposes the reverse of the <em>natural
     * ordering</em>.
     *
     * <p>The returned comparator is serializable and throws {@link
     * NullPointerException} when comparing {@code null}.
     *
     * @param  <T> the {@link Comparable} type of element to be compared
     * @return a comparator that imposes the reverse of the <i>natural
     *         ordering</i> on {@code Comparable} objects.
     * @see Comparable
     * @since 1.8
     */
    public static <T extends Comparable<? super T>> Comparator<T> reverseOrder() {
        return Collections.reverseOrder();
    }

    /**
     * Returns a comparator that compares {@link Comparable} objects in natural
     * order.
     *
     * <p>The returned comparator is serializable and throws {@link
     * NullPointerException} when comparing {@code null}.
     *
     * @param  <T> the {@link Comparable} type of element to be compared
     * @return a comparator that imposes the <i>natural ordering</i> on {@code
     *         Comparable} objects.
     * @see Comparable
     * @since 1.8
     */
    @SuppressWarnings("unchecked")
    public static <T extends Comparable<? super T>> Comparator<T> naturalOrder() {
        return (Comparator<T>) Comparators.NaturalOrderComparator.INSTANCE;
    }

 

거의 대부분이 default나 static으로 선언된 메소드인 것을 알 수 있다. 그리고 이런 메소드들은 구현체를 가지고 있다.

 

그러나 Interface의 기본적인 특징에 따라 default나 static으로 선언된 메소드가 아니라면 이는 추상 메소드로 반드시 재정의가 필요하다. (default로 선언된 메소드도 재정의가 가능하다)