///
Search
🏗️

Interface

태그
JAVA
인터페이스란 필자가 생각하기엔 객체를 바라보는 하나의 모양이라고 생각한다. 아래의 그림과 같은 형태를 보는 거다. 한 사람은 컵으로 볼 수 있고, 다른 사람은 사람의 형상 두가지를 볼 수 있다. 이렇듯 필자가 생각하기엔 인터페이스는 같은 형태를 다르게 볼 수 있도록 만들어주는 하나의 창이라고 생각한다. 물론, 백기선님은 규약이라고 이야기해주셨다. 근데 내가 설명하는 것은 인터페이스를 어떻게 바라볼까? 좀 더 쉽게 바라볼 수 없을까? class상속과 다르게 interface를 이야기 하려면 어떤 예제가 좋을까? 를 생각하며 이 그림과 설명을 만들었다.
그렇다면 정확한 인터페이스의 정의는 뭘까? 대충 oracle java tutorial의 내용에서는 interface를 다음과 같이 정의하고 있다. “서로 모르는 프로그래머들도 다른 그룹의 코드가 어떻게 작성되는지 몰라도 코드를 작성할 수 있어야 한다. 이러기 위해서는 일종의 계약, 규약이 필요하며 이러한 계약 또는 규약을 interface라 정의한다.” 한 마디로 규약이 맞다.

interface정의

interface를 정의할 때 아래와 같은 형태를 가질 수 있다. - 만약 상속 구조가 있을 경우(인터페이스가 인터페이스를 상속 받거나 다중으로 상속받는 경우) 서브 인터페이스는 수퍼인터페이스의 메서드까지 모두 구현해야한다. - 인터페이스 레퍼런스는 인터페이스를 구현한 클래스의 인스턴스를 가르킬 수 있고, 해당 인터페이스는 선언된 메서드만 호출할 수 있다.
public interface 인터페이스 명{ // 상수 타입 상수명 =; // public static final이 기본 값이다. // 추상 메소드 타입 메소드명(매개변수, ...); // public abstract가 기본이다. // 디폴트 메소드 default 타입 메소드명(매개변수, ...){ // 구현부 } // 정적 메소드 static 타입 메소드명(매개변수, ...){ // 구현부 } }
Java
복사

interface구현

interface의 경우 단독으로 사용하는 목적이 아닌 구현 이후 같은 타입에 맞추어(아까 위의 개념에서 설명한 모양을 맞춰주어) 갈아 끼우며 사용하기 위하여 사용한다. 그렇기 때문에 interface 단독으로는 abstract class와 같이 인스턴스를 만들지 못하며 구현해야 한다. interface의 경우 다중 상속이 가능하다. 물론 일반적 상속 메커니즘을 따르고 있으며, default 접근제어자가 붙은 메서드는 조금 특별히 선택적으로 재정의가 가능하다. 물론 static이 붙은 메서드와 private가 붙은 메서드는 재정의가 불가능하다. 물론 익명객체의 형식으로 만들어 사용할 수도 있고, 특별한 상황에서는 람다를 이용하여 구현할 수 있다.
public class 구현 클래스 명 implements 인터페이스 명 { // 인터페이스에 선언된 추상 메소드의 실체 메소드 선언 }
Java
복사

interface default method

인터페이스를 구현하는 클래스는 인터페이스에서 정의하는 모든 메서드 구현을 제공하거나 아니면 슈퍼클래스의 구현을 상속받아야한다. 이는 다시 말하면 인터페이스를 상속받는 구현해야하는 의무를 지닌 클래스는 인터페이스 내부에 정의된 모든 메서드를 구현해야한다. 이렇게 된다면 무슨일이 벌어질까? 예를 들어 내가 sort()라는 메서드를 인터페이스 내부에 정의하는 것을 까먹고 라이브러리를 출시했다. 차후 이를 알게 된 나는 모든 자료구조에 대한 sort를 다시 재정의해줘야한다. 이렇듯 나는 많이 당황스러울 것이다. 하지만 이를 해결하고자 새로운 기능이 자바 8에 추가 되었다. 기본 구현을 포함하는 인터페이스 정의방법을 두가지로 나누어 제공한다. 하나는 인터페이스 내부에 정적 메서드를 사용하는 것과 두번째로 인터페이스의 기본 구현을 제공할 수 있도록 디폴트 메서드 기능을 사용하는 것이다. 결과적으로 기존 인터페이스를 구현하는 클래스는 자동으로 인터페이스의 디폴트 메서드를 상속받게 되고 이를 구현해야하는 의무를 덜 수 있다.
위의 내용은 내가 이전에 default method에 대하여 공부하였을 때 기술한 내용이다. 꼭꼭 읽어주면 좋겠다. 포함하고 있는 내용은 다음과 같다 - default method의 탄생 - 개념 - 장점 - 인터페이스의 사용이 가져오는 효율성 - 디폴트 메서드를 활용한 예제 - 디폴트 메서드의 단점(다이아몬드 문제, 해결 규칙)

interface static method

처음엔 이걸 왜 만들었을까? 이런 생각을 조금 가졌다. 하지만 해당 기능은 유용한 코딩을 제공한다. 예를 들면 우리의 절친 Stream에서 조금의 해답을 찾을 수 있었다. Stream에서 제공하는 기능은 안다고 생각하고 static이 붙은 메서드와 구현하여 사용하는 메서드 두 종류가 존재한다. 근데 이게 API를 유심히 보다보니 특이점 하나를 발견할 수 있었다.
abstract method
static method
두 가지의 차이점이 조금 보이는가? 필자의 생각이지만 추상메서드의 경우 내가 현재 구현한 구현체 내부에 사용되는 값을 조작할 때 많이 사용된다. 이건 당연한거다. 왜냐하면 내가 넣어주는 값을 조작하는걸 알고 API를 만들어주지는 않기 때문이다. 하지만 특이한 건 static이 붙은 메서드이다. static의 경우에는 주로 값을 확인 하거나 외부의 파라미터를 통하여 들어온 값을 조작하여 새로운 객체를 생성하는 역할을 하는 메서드를 만들때 많이 사용된다. 이 귀찮은 걸 왜 저렇게 굳이 나눠서 만든 걸까? 필자의 생각으로는 뭔가 당연하게 와닿았다. 예를 들자면 객체 내부의 값을 조작해야한다면 당연히 기본적인 추상메서드를 제공해서 커스텀하게 할 것이다. 하지만 검사, 새로운 타입을 랩핑해서 줘야한다면 이야기가 다르다. 왜냐하면 이미 목표가 명확하게 정의되어 있기 때문이다. 조작이라는 말은 추상적이지만, null검사 또는 T 타입 배열생성과 같은 것은 목표가 명확하다. 단지 타입이 정의되어 있지 않을 뿐이다. 그렇기에 구현의 수고를 덜어주기 위하여 static을 이용하는 것이다. 하지만 이런 의문이 들 수 있다. “어? 그럼 default method 사용하면 되잖아?” 맞다. 하지만 default method도 결국 상속을 통하여 인스턴스를 만들어줄 수 있는 상황이 되어야 사용할 수 있다. 굳이 그 귀찮은 작업을 반복할 필요 없이 자주 사용하는 검사, 새로운 객체 생성 등의 기능은 static을 이용할 수 있도록 만들어준 것이다.
필자의 생각을 요약하자면 - default와 static의 차이는 결국interface 레벨에서 사용가능한가? 아닌가? 이다. - default를 사용해야하는 상황은 호환성 유지 및 기본 메서드 제공이 목적이다. - static을 사용해야하는 경우는 검사, 객체 생성과 같이 목표가 명확할 경우다. - 추상메서드를 사용해야하는 경우는 결국 사용자가 정의하여 사용해야하는 경우이다.

interface private method

이 친구도 나를 띠용하게 만들었다. 하지만 왜 필요한지는 위를 잘 보면 알 수 있다. “private” 즉, 남에겐 보여주면 안되는데 이걸 사용하는 애들은 모두 가지고 있어야하는 기능 제공해야 한다면 private 접근제어자를 사용하여 만들어주면 된다(java 9부터 가능하다). private 메서드도 큰 차이가 없다. 하지만 몇가지 규칙이 존재한다. - private 메서드는 구현부를 가져야한다. - 오직 interface 내부에서만 사용 가능 - private static 메서드는 다른 static 또는 static이 아닌 메서드에서 사용할 수 있다. - static이 아닌 private 메서드는 다른 private static 메서드에서 사용할 수 없다.
회고 뭔가 이번장을 공부하면서 이미 알고 있던 내용을 다시 상기시킨다는 느낌으로 공부를 했다. 그리고 평소 느낀? 것들 위주로 좀 정리해봤다. 예를 들자면 static, default 의 사용 차이같은 것을 말이다. 난 사실 아직도 abstract class가 크게 필요한가? 에 대한 의문이 좀 있다. 스프링을 사용하면서도 class 보단 interface를 사용하는 것이 습관 아닌 습관이 되었다(그리고 예전에 들은 토비의 스프링을 공부할때? 인 것 같다. 그때 우리는 스프링을 사용하는 습관이 solid 원칙을 준수하게 끔 만들어져 있기 때문에 모르지만 자연스러운 습관이 들어있다고 한다). 이렇듯 습관이 되어 어느정도의 차이는 알지만 꼭 이걸 써야한다는 결론에는 도달하지 못했다. 그걸 좀 더 찾아보고 알아봐야할 것 같다. 다른 분들의 정리 글을 많이 봤다. 그중에서 좀 기억에 남았던 것을 몇 가지 이야기해보겠다. 다음 링크는 내가 예전에 정리한 글이다. - 함수형 인터페이스 - 강한 결합, 느슨한 결합 오브젝트와 의존 관계 53p~87p