본문 바로가기
Java

자바 [JAVA] - Interface와 Class

by 2nyong 2023. 3. 23.

이번 포스트에서는 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로 선언된 메소드도 재정의가 가능하다)

댓글