2. Interface란 무엇인가?

kang·2021년 11월 27일
0

Spring Study

목록 보기
2/2

interface란 무엇인가?

오라클의 java se tutorial에서 이렇게 정의합니다.
"서로 다른 프로그래머 그룹이 소프트웨어 상호 작용(interact) 방식을 설명하는 '계약'에 동의하는 것이 중요한 소프트웨어 엔지니어링의 여러 상황이 있습니다. 각 그룹은 다른 그룹의 코드가 어떻게 작성되었는지 알지 못해도 자신의 코드를 작성할 수 있어야 합니다. 일반적으로 'interfaces'는 그러한 계약입니다." - java se tutorial interface편(구글 자동번역)

자바에서 Interface 정의(define)하는 방법

public interface GroupedInterface extends Interface1, Interface2, Interface3 {

    // constant declarations
    
    // base of natural logarithms
    double E = 2.718282;
 
    // method signatures
    void doSomething (int i, double x);
    int doSomethingElse(String s);
}

이 코드를 예시로 들면 접근제어자, interface, 이름, extends 키워드로 여러개의 상속받을 interface들을 지정하는 순으로 정의됩니다. 여기에서 알 수 있는 것은 Class 처럼 접근제어자가 있고 extends 키워드로 Interface를 상속받을 수 있다는 것에서 비슷해보입니다. 하지만 Class는 여러 Class를 동시에 상속할 수 없지만 Interface는 여러 Interface를 동시에 상속받을 수 있습니다.

또한 기본적으론 추상(Abstract) Class의 추상처럼 추상 Method들의 기본적인 Method 선언들이 구현이 없습니다. 위의 예제에는 등장하지는 않지만 Default Method라는 것이 존재하는데 Interface로 선언된 Method를 활용해 추가적인 기능들을 구현하는 역할을 합니다.(따라서 Method 본문이 존재합니다.) 더불어서 기능을 추가할 때 발생하는 interface 구현들의 변경을 최소화해주는 역할을 합니다. Class에서 존재하는 정적(Static) Method도 존재합니다.(이것도 Default와 같이 Method의 본문이 interface 내부에 존재합니다.) 그리고 아무런 접근제어자가 없다면 기본적으로 public 상태로 지정됩니다.
Abstract, Default, Static 총 3종류의 Method가 Interface에 존재합니다.

자바에서 interface 구현(implement)하는 방법, 레퍼런스를 통해 사용하는 방법

interface는 추상 Class와 같이 정의(define)가 있다고 바로 객체로 만들어서 사용할 수 없습니다.(instantiate)
왜냐하면 추상 Class 같이 기능이 구현되어 있는 것이 존재하는 것이 없습니다. 그러면

public interface Area {
    double getArea();
    default boolean isLargerThan(Area other) {
        return this.getArea() > other.getArea();
    }
}

위와 같은 interface가 존재하고 Rectangle과 Circle이라는 서로 다른 Class가 이 Area Interface를 구현한다고 가정합니다.

public class Rectangle implements Area {
	private double x, y;

	public Rectangle(double x, double y) {
		this.x = x;
		this.y = y;
	}

	public double getArea() {
		return this.x * this.y;
	}
}

Interface를 구현하는 Class면 java 컴파일러에게 implements 키워드를 통해 알려주고 정의된 추상 Method를 구현해줘야 컴파일이 진행됩니다. 물론 implements 키워드와 Area interface를 제외해도 컴파일은 성공하지만 같은 interface라고 인정해주지 않기 때문에 밑에서 설명할 예제가 작동하지 않을 것 입니다.
만약 우리는 이런 Rectangle Class 구현만 알고 있고 Circle Class는 Area interface를 구현하고 있는 것만 알고 있다고 가정하고 밑에 예제를 봅시다.

public class ex01 {
	public static void main(String args[]) {
		Rectangle rect1 = new Rectangle(2, 4);
		Rectangle rect2 = new Rectangle(4, 9);
		Circle circle = new Circle(3);

		System.out.println("rect1: " + rect1.getArea());
		System.out.println("rect2: " + rect2.getArea());
		System.out.println("circle: " + circle.getArea());

		System.out.println("rect1 > rect2 : " + rect1.isLargerThan(rect2));
		System.out.println("rect1 > circle : " + rect1.isLargerThan(circle));
		System.out.println("rect2 > circle : " + rect2.isLargerThan(circle));

		Area[] areas = { rect1, rect2, circle };
		System.out.print("Area[] : ");
		for (Area a: areas) {
			System.out.print(a.getArea() + " ");
		}
		System.out.println();
	}
}

우리는 Circle의 구현을 알지 못합니다. 하지만 interface를 통해 getArea Method가 구현된 상태라는 것을 자바 컴파일러를 통해 알 수 있습니다. 또한 추상 Class 처럼 타입 캐스트로 서로 다른 Class 객체를 같은 Interface 객체로 사용할 수 있습니다. 또한 interface 내에 구현되어 있는 Default Method들도 사용할 수 있죠.

궁금증

이것들을 진행하고 갑자기 문뜩 든 생각은 interface와 추상 Class의 차이는 결국 상속받은 것에서 상태를 저장하거나 아니라는 것의 차이라는 것 입니다. 왜냐하면 추상 Class는 일반적인 Class 처럼 멤버 변수들도 가지고 있고 추상 Method 뿐만 아니라 오버라이딩이 필요없는 Method들도 존재합니다. 이러면 상위 추상 Class의 구현에 무엇인가 멤버 변수가 변화한다는 특징이 존재하면 복잡도가 늘어날 수 밖에 없습니다. 그래도 다행인 것은 java는 class의 다중 상속을 지원하지 않는다는 특징을 가지고 있어서 다행입니다. 아니면 많은 멤버 변수 관리 지옥에 빠졌을 것 같네요.
이런 부분에서는 interface는 각 class의 구현에 자율성을 보장해주면 Method의 규격만 제시하는 느낌이라 코드 간 결합도가 내려가는 것 같다고 느꼈습니다.

참고 자료

java se tutorial - 상속 -> interface 편

과제 코드

2주차
블로그 예제

profile
맨정신 아닌 리눅서

0개의 댓글