[STUDY HALLE] 8주차 과제: 인터페이스

2 minute read

학습 목표

자바의 인터페이스에 대해 학습하세요.

  • 인터페이스 정의하는 방법
  • 인터페이스 구현하는 방법
  • 인터페이스 레퍼런스를 통해 구현체를 사용하는 방법
  • 인터페이스 상속
  • 인터페이스의 기본 메소드 (Default Method), 자바 8
  • 인터페이스의 static 메소드, 자바 8
  • 인터페이스의 private 메소드, 자바 9

Deadline: ~2021/01/09 13:00

정의 방법

인터페이스(interface)는 클래스들이 구현해야 하는 동작을 지정하는데 사용되는 추상 자료형이다. 내가 이해한대로 풀어 설명하자면, 인터페이스는 기능 명세서이다.

public interface 인터페이스명{
    타입 상수명 = ; //컴파일때 자동으로 public static final

    타입 메소드명(); //컴파일때 자동으로 public abstract
}

인터페이스의 모든 메소드는 추상메소드이고, 변수는 상수로 강제되므로 컴파일러에서 알아서 접근제어자를 붙여준다.

구현 방법

인터페이스는 추상클래스와 같이 직접 인스턴스를 생성할 수 없고, 클래스를 통해서 구현해야한다.

public interface Animal{
    void growl();
}

public class Cat implements Animal {

    @Override
    public void growl() {
        System.out.println("야옹");
    }
}

implements 라는 키워드를 통해서 해당 클래스에 적용할 수 있고, 인터페이스 내부에 정의된 메소드를 반드시 구현해야한다.

레퍼런스를 통해 구현체 사용

public class Dog implements Animal{
    @Override
    public void growl() {
        System.out.println("멍멍");
    }

    public void name() {
        System.out.println("바둑이");
    }
}

public class test{
   public static void main(String[] args) {
      Animal cat = new Cat(); 
      Dog dog = new Dog();
      
      cat.growl();
      dog.growl();
   }
}

위 처럼 구현체를 통해 Animal 인터페이스의 객체 생성이 가능하다.

Dog dog1 = new Dog();
Animal dog2 = new Dog();

dog1 같은 경우는 헷갈릴 일이 없지만, dog2는 name()메소드를 호출할 수 있을까? 클래스를 상속받는 경우와 같이, 호출할 수 없다. 사실 여기까지 본다면 클래스라는 개념을 두고 굳이 인터페이스가 왜 나왔는지 의문점이 들 수 있다.

상속

추상 클래스와 매우 비슷한 개념인 인터페이스의 주요 특징 중 하나가 다중상속이 가능하다는 것이다. 자바에서는 다이아몬드문제 때문에 클래스의 다중상속을 제한한다. 다이아몬드 문제 GrandFather클래스의 메소드를 FatherA 와 FatherB가 각각 오버라이딩하여 구현했다고 하자. 이러한 상황에서 Son클래스가 해당 메소드를 호출하게 되면, 어느 클래스에서 상속받은 메소드를 호출한건지 모호한 상황이 발생한다. c++같은 경우는 어떤 부모클래스를 통해 간접으로 상속받을 건지 명시해주거나(예를 들어, FatherA::method()) 가상 함수라는 개념을 통해 해결하는데, 자바는 아예 불가능하도록 해놨다.
기껏 클래스 다중 상속을 금지해놓고, 왜 인터페이스는 허용을 해준걸까? 그 이유는 바로 인터페이스는 다이아몬드 문제가 발생할 수 없기 때문이다.

interface GrandFather {
    void myMethod();
}
interface FatherA extends GrandFather {
    @Override
    void myMethod();
}

interface FatherB extends GrandFather {
    @Override
    void myMethod();
}

interface Son extends FatherA, FatherB{
    @Override
    void myMethod();
}

위의 예시를 보면 바로 알 수 있듯이, 인터페이스는 실제 구현을 하지 않기 때문에 충돌할 것이 없다.

기본 메소드

인터페이스의 기본 메소드(default method)는 자바8에서부터 추가된 기능이다. 기본 메소드를 통해서 인터페이스 내부에 코드를 구현할 수 있는데, 이때는 위에서 말한 다중 상속 문제가 발생하므로 기본 메소드를 새롭게 오버라이딩해주어야 컴파일이 된다.

public interface Animal{
    default void growl(){
      System.out.println("...");
    };
}

기본 메소드는 구현체에서 필수로 구현할 필요없이 사용할 수 있다. 인터페이스의 근본적인 역할에 역행하는 이러한 기능을 넣은 이유는 하위 호환성 때문이다. 만약 인터페이스에 어떤 메소드를 추가하면, 해당 인터페이스를 사용한 클래스들은 모두 오류가 발생하게 된다. 따라서 이러한 문제를 해결하기 위해서 인터페이스에 메소드를 구현할 수 있도록 한 것이다.

static 메소드

기본 메소드와 함께 자바8 부터 도입된 기능으로, 클래스에서의 static 메소드와 같은 동작을 한다. default 와의 차이점은 static 메소드이므로 상속되지 않는다는 점에 있다. 그리고 참조변수로는 호출할 수 없고, 반드시 클래스 명으로 메소드를 호출해야한다.

private 메소드

자바9 부터는 private 메소드와 private static 메소드라는 새로운 기능이 추가되었다. default 메소드와 static 메소드는 기본적으로 public이기 때문에 다른 인터페이스나 클래스가 접근하는 것을 원하지 않더라도 어쩔 수 없었지만 private 를 지원하면서 인터페이스에 대한 캡슐화를 가능하게했다.

그런데 이쯤되니 ‘아니 뭐 다 되게 해놨네’라는 생각이 든다. 이게 과연 인터페이스의 정의와 철학에 맞는 방향인가? 라는 의문점이 생기는데, 어쨋든 개발자의 편의를 위해 발전하는 방향이라고 생각하기로 했다.

참고문헌

https://medium.com/webeveloper/%EC%9E%90%EB%B0%94-%EC%9D%B8%ED%84%B0%ED%8E%98%EC%9D%B4%EC%8A%A4%EC%99%80-%EC%B6%94%EC%83%81%ED%81%B4%EB%9E%98%EC%8A%A4-6eecbe5d6350
https://siyoon210.tistory.com/125
http://www.tcpschool.com/java/java_polymorphism_interface

Leave a comment