Haneul's Blog

[Java] 인터페이스 본문

Java

[Java] 인터페이스

haneulss 2022. 10. 19. 18:37

목표 [백기선 자바 스터디 8주차]

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

학습할 것

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

 

인터페이스 정의하는 방법

인터페이스를 정의하는 방법을 알기 전에 먼저 인터페이스가 무엇인지부터 가볍게 알고 넘어가겠습니다.

 

인터페이스란?

인터페이스는 일종의 추상클래스로 추상메서드를 갖지만 추상클래스보다 추상화의 정도가 높아서 추상클래스와 달리 일반 메서드 또는 멤버변수를 구성원으로 가질 수 없습니다.
즉, 오직 추상메서드와 상수만을 멤버로 가질 수 있으며, 그 외의 다른 어떠한 요소도 허용하지 않습니다.

 

하지만 Java8 이후부터는 default method와 static method가 추가되어서 일반 메서드와 static 메서드를 구현할 수 있게 되었습니다.

또한 Java9 이후부터는 private method도 추가되었습니다.

 

그래서 Java9 이후에는 아래와 같은 예시로 인터페이스를 정의할 수 있습니다.

public interface InterfaceTest{
    // 상수 -> 타입 상수명 = 값;
    // public static final 타입 = 값; 과 동일
    int a = 1;
    

    // 추상 메서드 -> 타입 메서드명(매개변수, ...);
    // public abstract와 동일
    int a(int b);

    // 디폴트 메서드 -> default 타입 메서드명(매개변수, ...) { // 구현부 }
    default int b(int c) {
        return c + 2;
    }
    
    // 정적 메서드 -> static 타입 메서드명(매개변수, ...){// 구현부}
    static int c(int d) {
        return 123;
    }
    
    // private 메서드 -> private 타입 메서드명(매개변수, ...) {// 구현부}
    private void privateCarMethod() {        
	 System.out.println("private method");    
    }
}

하나씩 설명하면 아래와 같습니다.

  1. 상수
    인터페이스에서 값을 정해주면 값을 바꿀 수 없고 이를 참조만 가능
  2. 추상 메서드
    메서드 시그니처만 있고 이를 오버라이딩하여 해서 구현하여 사용
  3. 디폴트 메서드
    인터페이스에서 기본적으로 제공하고, 원하면 오버라이딩해서 사용(기존의 클래스의 메서드를 상속해서 받는 메서드와 동일)
  4. 스태틱 메서드
    인터페이스에서 제공해주는 것을 무조건 사용
  5. private 메서드
    자바8에서 디폴트, 스태틱 메서드가 추가되었지만 하나 문제점이 있습니다. 내부에서만 사용할 메서드가 외부에 공개된다는 점인데, 이를 방지하기 위해서 private method와 private static method가 나오게 되었고 캡슐화에 용이하게 되었습니다.

 

그렇다면 인터페이스는 왜 사용할까요?

인터페이스는 여러 장점을 가지고 있고 이를 이용하여 개발의 편의성과 확장성을 가져다 주기 때문에 사용합니다.
장점은 아래와 같습니다.

  1. 개발 시간 단축
    인터페이스가 작성되면 이를 사용하여 프로그램을 작성하고 오버라이딩 하여 사용하면 되기 때문에 개발 시간이 단축됩니다.
  2. 표준화 기능
    프로젝트에 사용되는 기본 틀을 인터페이스로 작성한 다음, 개발자들에게 인터페이스를 구현하여 프로그램을 작성하도록 하면 보다 일관되고 정형화된 프로그램의 개발이 가능합니다.
  3. 서로 관계 없는 클래스들 간의 관계를 맺어줍니다.
    하나의 인터페이스를 공통적으로 구현하도록 하여 관계를 맺어줄 수 있습니다.
    예를 들면 RC카와 진짜 차 간의 관련성은 크게 없지만 인터페이스에서 메서드로 drive()라는 메서드를 가지고 이를 둘 다 상속을 받아 구현하면 상관없는 클래스들 간의 관계가 맺어집니다.
  4. 독립적인 프로그래밍 가능
    인터페이스를 이용하면 클래스의 선언과 구현을 분리시킬 수 있기 때문에 실제 구현에 독립적인 프로그램을 작성하는 것이 가능합니다.

 

인터페이스를 구현하는 방법

인터페이스는 일반적인 클래스의 상속과 다르게 구현할 때 아래의 예시와 같이 implements를 사용합니다.

interface Car{
	void drive();
}

class Bently implements Car{
    @Override
    public void drive(){
        System.out.print("벤틀리 운전중");
    }
}

 

또한 인터페이스를 상속받게 되면 클래스와 달리 아래와 같이 여러 개의 인터페이스를 상속 받을 수 있습니다.

interface Car{
	void drive();
}

interface Owner {
	void owner();
}

class Bently implements Car, Owner{

    @Override
    public void drive(){
	    System.out.print("벤틀리 운전중");
    }
    
    @Override
    public void owner(){
	    System.out.print("벤틀리 주인은 나~");
    }
}

 

인터페이스 레퍼런스를 통해 구현체를 사용 및 상속

인터페이스를 통해서 다형성을 통한 프로그래밍의 확장을 극대화 시킬 수 있습니다.
그 이유는 인터페이스도 결국 상속받은 클래스들의 조상 타입이 되기 때문에 다형성에 의해 자손 클래스의 인스턴스를 조상타입의 참조변수로 참조가 가능하기 때문입니다.

아래의 예시를 보면 더 이해하기 수월할 수 있습니다.

interface Car{
	void drive();
}

class Bently implements Car{

    @Override
    public void drive(){
	    System.out.print("벤틀리 운전중");
    }
}

class K3 implements Car{

    @Override
    public void drive(){
	    System.out.print("K3 운전중");
    }
}

class Main{
    public static void main(String[] args) {
        Car car1 = new Bently();
        Car car2 = new K3();

        car1.drive();
        car2.drive();
    }
}

위의 예시를 보면 Bently와 K3 클래스가 Car 인터페이스를 상속받아서 실제 구현할 때는 Car 인터페이스가 Bently, K3 클래스를 구현체로 쓰는 것을 볼 수 있습니다.

 

 

'Java' 카테고리의 다른 글

[Java] 멀티쓰레드 프로그래밍  (0) 2022.10.22
[Java] 예외 처리  (0) 2022.10.20
[Java] 패키지  (0) 2022.10.18
[Java] 상속  (0) 2022.10.17
[Java] 클래스  (0) 2022.10.16