Java/라이브스터디

인터페이스

목표

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

학습할 것 (필수)

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

 


 

인터페이스

인터페이스란, 일반적으로 상수와 추상메소드로만 이루어진 클래스를 의미합니다.

인터페이스의 정의

  • 상수 : public static final 로 선언된 변수
  • 추상메소드 : abstract 로 선언된 메소드. 구현부가 없다.

 

public interface sample{
    public static final int value = 10;
    public abstract void method();
    public void method1();
}

인터페이스에서 메소드의 경우, abstract 를 붙히지 않아도 바이트코드 변환시에 abstract 가 자동으로 붙게됩니다.

 

 

인터페이스의 구현

public interface sample{
    public static final int value = 10;
    public abstract void method();
    public void method1();
}

public class MyCLASS implements sample{
    @Override
    public void method() {
        System.out.println("MyCLASS");
    }

    @Override
    public void method1() {

    }

}

public class MyCLASS2 implements sample{
    @Override
    public void method() {
        System.out.println("MyCLASS2");
    }

    @Override
    public void method1() {

    }
}

인터페이스의 구현은 해당 인터페이스를 상속하는 클래스에서 이루어지며, 동일한 인터페이스를 상속하더라도 추상메소드의 내용이 같을 필요는 없습니다.

 

 

인터페이스 참조를 통한 구현체의 사용

// 인터페이스를 상속하는 클래스의 객체를 통한 접근
MyCLASS myCLASS = new MyCLASS();

myCLASS.method();

// 인터페이스 타입의 객체선언 시, 익명생성자를 통하여 재정의
sample sample = new sample() {
    @Override
    public void method() {

    }

    @Override
    public void method1() {

    }
};

인터페이스에 대한 접근은 다음과 같은 방법이 있습니다.

  1. 인터페이스를 상속하는 클래스의 객체를 통한 접근
  2. 인터페이스 타입의 객체선언 시, 익명생성자를 통하여 재정의

 

인터페이스의 상속

public class MyCLASS implements sample{
    @Override
    public void method() {
        
    }

    @Override
    public void method1() {

    }
}

인터페이스는 implements를 이용한 다중상속이 가능합니다.
인터페이스를 상속하는 클래스는 반드시 추상클래스를 재정의 하여야하며, 인터페이스의 내용은 해당 클래스에서 구현됩니다.

 

 

public interface sample{
    public static final int value = 10;
    public abstract void method();
    public void method1();
}

public interface sub extends sample {
    public abstract void show();
}

public class MyCLASS implements sub{
    @Override
    public void method() {

    }

    @Override
    public void method1() {

    }

    @Override
    public void show() {

    }
}

인터페이스끼리는 implements를 통한 상속이 불가능하며, extends를 통한 상속을 해야합니다.
이렇게 인터페이스를 extends하는 인터페이스를 implements하는 클래스는 extends하는 인터페이스의 추상메소드도 재정의 해야합니다.

 

 

자바 8 이후의 인터페이스

자바 8에 들어오면서 람다라는 기능이 추가되고, 기존의 추상메소드와 상수만 작성이 가능하던 인터페이스에 default 메소드와 static 메소드라는 기능이 추가되었습니다.

 

 

default 메소드

public interface sample{
    public static final int value = 10;
    public abstract void method();
    public void method1();
    // 자바 8 이전, 인터페이스에 선언 가능하던 요소들.

    public default void default_method(){
        System.out.println("Default!");
    }
    // 자바 8에서 추가된 default 메소드
}


public class MyCLASS implements sample{
    @Override
    public void method() {
        System.out.println("MyCLASS");
    }

    @Override
    public void method1() {

    }

    @Override
    public void default_method(){
        System.out.println("Overrided");
    }// 선택사항
}

눈에 띄는 특성으로는 인터페이스의 메소드에게 구현부가 생겼습니다.
default 키워드로 선언된 메소드는 구현부를 반드시 정의해주어야 하며, 해당 메소드는 인터페이스를 상속하는 클래스에서 반드시 재정의될 필요는 없습니다.

 

 

MyCLASS myCLASS = new MyCLASS();
myCLASS.default_method();

sample sample = new sample() {
    @Override
    public void method() {

    }

    @Override
    public void method1() {

    }
};


sample.default_method();

== 출력 결과 == 

Overrided
Default!

default 메소드의 경우 선택적 재정의가 가능하며, 재정의를 하지 않았을 시에는 인터페이스에서 선언된 구현부가 실행됩니다.

 

 

static 메소드

public interface sample{
    public static final int value = 10;
    public abstract void method();
    public void method1();
    // 자바 8 이전, 인터페이스에 선언 가능하던 요소들.

    public default void default_method(){
        System.out.println("Default!");
    }
    // 자바 8에서 추가된 default 메소드

    public static void static_method(){
        System.out.println("Static!");
    }
    // 자바 8에서 추가된 static 메소드
}

static 메소드의 경우, 객체를 이용한 접근은 불가능하며 클래스명을 이용한 접근이 가능합니다.

 

 

sample.static_method();

sample obj = new sample() {
    @Override
    public void method() {
        
    }

    @Override
    public void method1() {

    }
};

obj.static_method();
// 불가능.

상속받는 클래스에서 메소드명 만을 이용한 호출과 객체를 통한 접근이 불가능하며, 오직 클래스명을 이용한 메소드 호출이 가능합니다.

 

 

public interface sample{
    public static final int value = 10;
    public abstract void method();
    public void method1();
    // 자바 8 이전, 인터페이스에 선언 가능하던 요소들.

    public default void default_method(){
        System.out.println("Default!");
    }
    // 자바 8에서 추가된 default 메소드

    public static void static_method(){
        System.out.println("Static!");
    }
    // 자바 8에서 추가된 static 메소드
}
// sample 인터페이스

public class MyCLASS implements sample{
    @Override
    public void method() {
        System.out.println("MyCLASS");
    }

    @Override
    public void method1() {

    }

    @Override
    public void default_method(){
        System.out.println("Overrided");
    }

    public void static_method(){
        System.out.println("What is this?");
    }
}
// MyCLASS 클래스 ( sample 상속 )

public class SUBMAIN {
    public static void main(String[] args) {
        MyCLASS myCLASS = new MyCLASS();
        myCLASS.default_method();
        myCLASS.static_method();
        sample.static_method();
    }
}

== 출력 결과 ==

Overrided
What is this?
Static!

정적인 메소드이기 때문에, 재정의 또한 불가능합니다.


상속하는 클래스에서 동일한 이름의 메소드를 새롭게 정의하는 것은 가능하며, 그렇게 생성된 메소드는 인터페이스의 메소드와 다른 메소드가 됩니다. (즉, 재정의한게 아님)

 

 

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

public interface sample{
    public static final int value = 10;
    public abstract void method();
    public void method1();
    // 자바 8 이전, 인터페이스에 선언 가능하던 요소들.

    public default void default_method(){
        System.out.println("Default!");
        private_method();
    }
    // 자바 8에서 추가된 default 메소드

    public static void static_method(){
        System.out.println("Static!");
    }
    // 자바 8에서 추가된 static 메소드

    private void private_method(){
        System.out.println("Private!");
    }
    // 자바 9에서 추가된 private 메소드
}

public class SUBMAIN {
    public static void main(String[] args) {
        MyCLASS myCLASS = new MyCLASS();
        myCLASS.default_method();
        myCLASS.static_method();
        sample.static_method();

        //myCLASS.private_method();
        //불가능

        //sample.private_method();
        //불가능
    }
}

private 접근지시자를 interface에서 사용할 수 있습니다.
해당 접근 지시자가 붙은 메소드의 경우, 상속받는 클래스나 클래스 명을 이용한 접근 둘 다 불가능하며, 인터페이스 내부의 default 메소드에서 호출할 수 있습니다.

 

 

참고자료