본문 바로가기
자바/스터디

[자바 스터디] 8주차 과제 - 인터페이스

by jeonghaemin 2021. 1. 8.
728x90

본 게시글은 백기선 님의 live-study 과제를 수행하면서 작성한 글입니다.

목표

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

학습할 것 (필수)

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

인터페이스 정의하는 방법

public interface Car {

    public static final int MAX_SPEED = 200;
    public abstract void move();
    void stop(); //제어자 생략
}

인터페이스를 정의하는 방법은 클래스를 정의하는 방법과 비슷하다. class 키워드를 대신해서 interface 키워드를 사용한다.

  • 모든 멤버변수는 public static final 이어야 하며, 생략 가능하다.
  • 모든 메소드는 public abstract 이어야 하며, 생략 가능하다(JDK1.8부터 static 메소드와 default 메소드는 예외)

생략된 제어자는 컴파일러가 추가해준다. 원래 인터페이스는 모든 메소드가 추상메소드이어야 했는데, JDK1.8 버전 이후 static 메소드와 디폴트 메소드의 추가를 허용하는 것을 변경되었다.

인터페이스 구현하는 방법

인터페이스 그 자체로는 인스턴스를 생성할 수 없으며, 추상클래스가 상속을 통해 추상메소드를 완성하는 것처럼 인터페이스를 구현해주는 클래스를 생성하여 추상 메소드를 구현하여 사용할 수 있다.

다만 인터페이스의 구현은 상속과 달리 implements 키워드를 사용한다.

public class Tesla implements Car{
    @Override
    public void move() {
        //구현 코드
    }

    @Override
    public void stop() {
        //구현 코드
    }
}

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

인터페이스 타입의 참조 변수로 이를 구현한 클래스의 인스턴스를 참조할 수 있으며, 인터페이스 타입으로의 형변환도 가능하다.

interface Car {
    //code..
}

class BMW implements Car {
    //code..
}
class Benz implements Car {
    //code..
}
class Tesla implements Car {
    //code..
}

public class Main {
    public static void main(String[] args) {
        Car benz = new Benz();
        Car bmw = new BMW();
        Car tesla = new Tesla();

        Car[] cars = new Car[3];
        cars[0] = benz;
        cars[1] = bmw;
        cars[2] = tesla;
    }
}

이를 이용하여 서버 쪽의 변경 가능성이 있는 코드가 있더라도 해당 코드를 인터페이스 타입으로 선언하면 클라이언트의 코드에는 영향을 주지 않고 서버 쪽에서 구현체만 바꿔주면 되기 때문에 효율적으로 프로그램을 작성할 수 있다.

인터페이스 상속

인터페이스는 인터페이스로부터 상속 받을 수 있으며, 클래스와 달리 다중 상속이 가능하다.

interface ElectricCar {
    //code..
}

interface OilCar {
    //code..
}
public interface HybridCar extends ElectricCar, OilCar{
  //code..
}

인터페이스의 기본 메소드 (Default Method), 자바 8

디폴트 메소드는 추상 메소드의 기본적인 구현을 제공하는 메소드로, 기본적인 구현을 제공하기 때문에 추상 메소드와 달리 구현이 선택적이다.

그렇기 때문에 디폴트 메소드를 이용하여 인터페이스에 변경이 생겨도 인터페이스를 구현한 클래스의 변경이 일어나지 않도록 할 수 있다.

interface Greeting {
    default void hello() {
        System.out.println("Hello!");
    }
}

class GreetingImpl implements Greeting {}

public class Main {
    public static void main(String[] args) {
        Greeting greeting = new GreetingImpl();
        greeting.hello();

        //결과 : Hello!
    }
}

인터페이스의 static 메소드, 자바 8

자바8이 나오면서 인터페이스에 static메소드를 추가할 수 있게 되었다. 자바 8이 나오기 전까지는 인터페이스의 모든 메소드는 추상 메소드이어야 했기 때문에 인터페이스와 관련된 static메소드는 별도의 클래스를 이용해야 했다.

대표적으로 java.util.Collection 인터페이스가 있는데 이 인터페이스와 관련된 static메소드들은 java.util.Collections클래스에 포함되어 있다.

interface Greeting {
    static void hello() {
        System.out.println("Hello!");
    }
}

public class Main {
    public static void main(String[] args) {
        Greeting.hello();

        //결과 : Hello!
    }
}

인터페이스의 private 메소드, 자바 9

자바9부터 인터페이스에 private, private static 메소드가 허용이 되었다.

interface Hello { 
    private static void method1() {
        System.out.println("interface private static method");
    }

    private void method2() {
        System.out.println("interface private method");
    }
}

참고

  • 자바의 정석 3판(남궁성 저)

댓글