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

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

인터페이스 정의하는 방법

  • 자동적으로 상수와 추상 메소드가 선언된다.
  • 멤버 변수에는 public static final이 자동으로 붙는다.
  • 메소드에는 public abstract가 자동으로 붙는다.
  • 형식적인 선언만 있고 구현은 없다.
interface 인터페이스 이름 {
   public static final float pi = 3.14;
   public void add();
}

인터페이스의 요소

상수

  • 모든 변수는 상수로 변환

추상 메소드

  • 모든 메소드는 추상 메소드로 구현
  • 모든 메소드의 접근 지정자는 public 이며 생략 가능

디폴트 메소드 java 8

  • 기본 구현을 가지는 메소드, 구현 클래스에서 재정의 할 수 있음

정적 메소드 java 8

  • 인스턴스 생성과 상관 없이 인터페이스 타입으로 사용할 수 있는 메소드

private 메소드 java 9

  • 인터페이스를 구현한 클래스에서 사용하거나 재정의 할 수 없음. 인터페이스 내부에서만 기능을 제공하기 위하여 구현하는 메서드

추상클래스와 인터페이스의 공통점과 차이점

공통점

  • 자기 자신을 객체화할 수 없으며 다른 객체가 상속 (extends) , 구현 (implements)를 하여 객체를 생성할 수 있다.
  • 상속 (extends) , 구현 (implements)한 하위 클래스에서는 상위에서 정의한 추상메서드를 반드시 구현해야 한다.

차이점

추상 클래스 인터페이스
일반 메소드 포함 가능 모든 메서드는 추상 메서드
자바 8 이후 default, static 메소드 추가 가능
다중상속 불가 다중상속 가능
상수, 변수 필드 포험 가능 상수필드만 포함 가능

 

추상클래스는 "is-a : ~는 ~이다" 의 개념이다.
인터페이스는 "has-a : ~는 ~를 할 수 있다." 의 개념이다.

인터페이스 구현하는 방법

  • implements 키워드를 사용
  • 인터페이스에 정의되어 있는 메소드를 필수적으로 구현해야 한다.
  • 구현 시, 부모의 메소드보다 넓은 법위의 접근제어자를 사용해야 한다.
public class Cat implements Animal {

    @Override
    public String getName() {
        return "고양이";
    }

    @Override
    public int getLegs() {
        return 4;
    }

}

인터페이스와 다형성

  • 인터페이스는 clinet code와 서비스를 제공하는 객체 사이의 약속
  • 어떤 객체가 어떤 interface 타입이라 함은 그 interface가 제공하는 메서드를 구현했다는 의미
  • Client는 어떻게 구현되었는지 상관없이 interface의 정의만을 보고 사용할 수 있다.
  • 다양한 구현이 필요한 인터페이스를 설계하는 일은 매우 중요한 일이다.

인터페이스 레퍼런스를 통해 구현체를 사용하는 방법

  • 다형성의 특징을 활용하여 인터페이스를 타입으로써 사용가능
public interface TestInterface {
    void print();
}
class TestClass2 implements TestInterface {
    @Override
    public void print() {
        System.out.println("Class1_override");
    }
}
public class TestClass implements TestInterface{
    @Override
    public void print() {
        System.out.println("Class_override");
    }
    public void TestClass1(TestInterface testInterface) {
        testInterface.print();
    }

    public static void main(String[] args) {
        TestInterface testInterface = new TestClass();
        TestInterface testInterface2 = new TestClass2();

        testInterface.print();
        testInterface2.print();

        TestClass testClass = new TestClass();
        testClass.print();
    }
}

//Class_override
//Class1_override
//Class_override


인터페이스 상속

  • 서브 인터페이스는 수퍼 인터페이스의 메서드까지 모두 구현해야 한다.
  • 인터페이스 레퍼런스는 인터페이스를 구현한 클래스의 인스턴스를 가리킬 수 있고,
    해당 인터페이스에 선언된 메서드만 호출 할 수 있다.
  • 클래스가 상속하는 것과 동일하게 extends 키워드를 사용하여 인터페이스를 상속할 수 있다

인터페이스 다중 상속

  • 클래스와 달리 다중 상속이 가능하다.
  • 상위 인터페이스에 있는 메서드 중 메서드 명과 파라미터 형식은 같지만 리턴 타입이 다른 메서드가 있다면,
    둘 중 어느것을 상속받느냐에 따라 규칙이 달라지게 되므로 다중 상속이 불가능하다.


인터페이스의 Default Method - 자바 8

기본 메소드

  • 해당 인터페이스를 구현한 클래스의 어떠한 영향 없이 새로운 기능을  추가하는 방법
  • 구현체가 모르게 추가된 기능이므로 그만큼의 리스크가 따른다.
    컴파일 에러는 발생하지 않지만 특정한 구현체의 로직에 따라 런타임 에러가 발생할 수 있다.
    문서화 필요
  • Object가 제공하는 equals, hasCode 와같은 기본 메소드는 제공 불가
  • 인터페이스를 상속받은 인터페이스에서 다시 추상 메소드로 변경할 수 없다.
public interface TestInterface {
    default void defaultmethod() {
        System.out.println("default");
    }
}


public interface TestInterface3 extends TestInterface{
    @Override
    private void defaultmethod() { // 불가 - 에러
        TestInterface.super.defaultmethod();
    }
}
  • 인터페이스 구현체가 default method를 재정의 할 수 있다.

하위 호환성

  • 인터페이스에 기능을 추가해도 이 인터페이스를 상속한 클래스들이 깨지지 않게 하는 것
  • default 메소드를 추가하면 하위 호환성은 유지하면서 인터페이스 보완을 진행할 수 있다.

클래스에서 두 인터페이스를 상속하는데 각 인터페이스에 같은 이름의 디폴트 메소드가 있다면?

public class Snake implements PrintableAnimal, Printer {

    // ...

    @Override
    public void print() {
        PrintableAnimal.super.print(); // PrintableAnimal의 print() 메소드 호출
        Printer.super.print(); // Printer의 print() 메소드 호출

        // 혹은 직접 구현...
    }
}

인터페이스의 Static Method - 자바 8

  • 객체 생성 없이 클래스 이름으로 메소드를 호출하는 것
  • 구현체 클래스에서 인터페이스명.메소드명 으로 접근
  • 구현체 클래스에서 오버라이딩이 불가능하다.
  • 메소드의 구현체를 가지고 있다.
  • 상속이 불가능하다.
interface In1 {
    static void test() {
        System.out.println("static method");
    }
}

public class TestClass implements In1{
    public static void main(String[] args) {
        In1.test(); // 인터페이스명.메소드명으로 접근한다.
    }
}

인터페이스의 Private Method - 자바 9

  • 자바 8에서 추가 된 default, static 메소드는 인터페이스 메소드와 더불어 public으로 만들어야 했다.
  • abstract로 선언할 수 없다.
  • 해당 인터페이스 안에서만 사용이 가능하다.
  • private static 으로 시작하는 메소드는 다른 메소드가 non-static 이든 static 이든 접근 가능하다.
  • private만 적용된 메소드는 static 메소드 안에서는 사용할 수 없다.
public interface PrintableAnimal extends Animal, Comparable<PrintableAnimal> {

    static String getDescription() {
        return "출력기능이 있는 동물 인터페이스";
    }

    // 자신의 메소드를 기본 메소드로 구현
    // private 메소드 사용
    default void print() {
        printName();
        printLegs();
    }
    
    // private 메소드로 기본 메소드에서 사용할 로직 분리 1
    private void printName() {
        System.out.println("이름 : " + getName());
    }
    
    // private 메소드로 기본 메소드에서 사용할 로직 분리 2
    private void printLegs() {
        System.out.println("다리개수 : " + getLegs());
    }

    // Comparable 인터페이스의 메소드를 상속하여 기본 메소드 구현
    @Override
    default int compareTo(PrintableAnimal o) {
        return getLegs() - o.getLegs();
    }

    default void otherDefaultMethod() {
        System.out.println("other default method");
    }
}

'Back-end > java' 카테고리의 다른 글

스터디 10주차 - 멀티쓰레드 프로그래밍  (0) 2021.07.02
스터디 9주차 - 예외 처리  (0) 2021.07.01
스터디 7주차 - 패키지  (0) 2021.07.01
스터디 6주차 - 상속  (0) 2021.06.30
스터디 5주차 - 클래스  (0) 2021.06.30

+ Recent posts