Langauge/Java-basic

[Java] 인터페이스란?

강잇 2022. 8. 7. 20:34

인터페이스 정의

  • 인터페이스는 '추상 메서드의 집합'이라고 정의할 수 있다.
  • 인터페이스는 기본적으로 상수와 추상 메서드만 가질 수 있어 추상 클래스보다 더 높은 추상성을 가지고 있다.
  • 추상 클래스와 비교한다면 추상 클래스는 '미완성 설계도', 인터페이스는 '밑그림'으로 나타낼 수 있다.

인터페이스 특징

  • interface 키워드를 이용해 인터페이스를 선언할 수 있다.
  • 인터페이스 내부의 모든 필드public static final 제어자로 정의된다.
    • 구현 객체의 같은 동작을 보장하기 위한 목적
    • public static final 제어자를 생략해도 컴파일러가 자동으로 추가한다.
  • 인터페이스 내부의 모든 메서드추상 메서드로 인식하기 때문에 따로 abstract 키워드를 사용하지 않는다.
    • 인터페이스의 메서드의 접근 지정자는 public으로 정의되기 때문에 오버라이딩 시 접근 지정자에 주의해야 한다.
    • 오버라이딩할 메서드는 기존 메서드의 접근 지정자의 범위가 크거나 같아야 한다.
  • 인터페이스는 다중 구현(상속)이 가능하다.
// 인터페이스 기본 구조
interface 인터페이스명 {
    // public static final : 생략 시 컴파일러가 자동으로 추가
    public static final 자료형 필드명 = 값; // 상수
    
    // public : 생략 시 컴파일러가 자동으로 추가
    public 리턴 타입 메서드명(); // 추상 메서드
}

인터페이스의 구현

  • 인터페이스의 추상 메서드는 하위 클래스에서 반드시 구현해야 한다.
  • 클래스를 상속할 때는 extends 키워드를 사용하지만 인터페이스는 implements 키워드를 사용한다.

인터페이스 단일 구현

// 인터페이스의 단일 구현 구조
class 클래스명 implements 인터페이스명 {
    // 인터페이스의 모든 추상 메서드 구현
}

인터페이스 다중 구현

  • 인터페이스는 다중 구현할 수 있다.
    • 모든 필드가 상수로 정의되어 있어 충돌이 발생할 수 없고, 메서드명이 겹치더라도 하위 클래스에서 실질적 기능을 구현하기 때문에 다중 구현이 가능하다.
  • 다중 구현할 때 인터페이스는 쉼표(,)로 구분한다.
// 인터페이스의 다중 구현
class 클래스명 implements 인터페이스명1, 인터페이스명2, ... {
    // 인터페이스의 모든 추상 메서드 구현
}

인터페이스 상속

  • 인터페이스끼리도 상속이 가능하다.
    • 인터페이스는 상수 또는 추상 메서드만 가질 수 있고 상속을 받는 멤버도 결국 상수와 추상 메서드이기 때문에 상속이 가능하다.
interface 인터페이스1 {
}
// 인터페이스1을 상속한 인터페이스2
interface 인터페이스2 extends 인터페이스1 {
}

상속과 구현

  • 아래의 코드처럼 인터페이스를 구현한 클래스를 상속할 수 있다.
// 상속과 구현 구조
class 클래스명 extends 클래스명 implements 인터페이스1, 인터페이스2, ... {
}

인터페이스 타입의 객체 생성

  • 인터페이스는 직접 객체를 생성할 수 없다.
  • 인터페이스 타입의 객체를 생성하는 방법은 인터페이스를 구현한 하위 클래스를 이용하는 방법과 익명 이너 클래스를 이용하는 방법이 있다.

하위 클래스의 생성자 이용

public class Main {
    public static void main(String[] args) {
        // 하위 클래스를 이용한 객체 생성
        ExamInterface examClass1 = new ExamClass();
    }
}
// 인터페이스 생성
interface ExamInterface {
    public void print();
}
// 인터페이스를 구현한 하위 클래스 생성
class ExamClass implements ExamInterface {
    @Override
    public void print() {
        System.out.println("하위 클래스를 이용한 객체 생성");
    }
}

익명 이너 클래스 이용

public class Main {
    public static void main(String[] args) {
        // 익명 이너 클래스를 이용한 객체 생성
        ExamInterface examInterface = new ExamInterface() {
            @Override
            public void print() {
                System.out.println("익명 이너 클래스를 이용한 객체 생성");
            }
        };
        examInterface.print();
    }
}
// 인터페이스 정의
interface ExamInterface {
    public void print();
}

자바 8 이후 인터페이스 변경 사항

  • 자바 8 이후부터는 인터페이스 내부에 디폴트 메서드와 정적 메서드를 포함할 수 있다.

디폴트 메서드란

  • 디폴트 메서드는 완성된 메서드로 하위 클래스에서 구현할 의무가 없는 메서드이다.
    • 구현할 의무가 없기 때문에 하위 클래스에서 구현하지 않아 발생하는 오류를 방지한다.
  • 오버라이딩이 가능하여 하위 클래스에서 상황에 맞게 오버라이딩을 할 수 있다.

디폴트 메서드 생성

// 디폴트 메서드 생성
interface 인터페이스명 {

    // public : 생략 시 컴파일러가 자동으로 추가
    // default : 생략 불가능
    public default 리턴 타입 메서드명 () {
        // 메서드 기능
    }
}

디폴트 메서드 호출

  • 디폴트 메서드는 하위 클래스에서 호출할 수도 있다.
// 디폴트 메서드 호출
부모 인터페이스명.super.디폴트 메서드명();

interface ExamInterface {
    // 디폴트 메서드 생성
    default void print() {
        System.out.println("ExamInterface.print() 호출됨");
    }
}
class ExamClass implements ExamInterface {
    public void print() {
        // 하위 클래스에서 디폴트 메서드 호출
        ExamInterface.super.print();
        System.out.println("ExamClass.print() 호출됨");
    }
}

static 메서드

  • static 메서드를 포함할 수 있어 객체를 생성하지 않고 정적 메서드를 호출할 수 있다.
// 인터페이스 내부의 정적 메서드 호출
인터페이스명.정적 메서드명();

// 정적 메서드 호출 예
public class Main {
    public static void main(String[] args) {
        // 인터페이스 내부의 정적 메서드 호출
        ExamInterface.print(); // 실행 : ExamInterface.print() 호출됨
    }
}

interface ExamInterface {
    static void print() {
        System.out.println("ExamInterface.print() 호출됨");
    }
}