본문 바로가기
블로그 이미지

방문해 주셔서 감사합니다! 항상 행복하세요!

  
   - 문의사항은 메일 또는 댓글로 언제든 연락주세요.
   - "해줘","답 내놔" 같은 질문은 답변드리지 않습니다.
   - 메일주소 : lts06069@naver.com


Java(자바)/Java 기본

Java 버전에 따른 인터페이스 상속 정리(자바 인터페이스 상속)

야근없는 행복한 삶을 위해 ~
by 마샤와 곰 2020. 12. 11.

 

자바에서 인터페이스(Interface)를 상속 받는 것은 implements 명령어를 통해서 가능합니다.

Java에서는 인터페이스를 n개 까지 상속(implements)받을 수가 있습니다.

자바에서 extends를 통해서 받는 상속은 단 1개만 가능하게 되어 있습니다.

 

 

#자바 7까지의 인터페이스 상속시 유의 사항 ─

 

 

간단하개 2개의 인터페이스와 1개의 상속받는 클래스를 만들어 살펴 보겠습니다.

그러면, 아래와 같은 2개의 인터페이스가 존재 합니다.

* 이름 : Test1

//첫번째 인터페이스
public interface Test1 {
    public final String NAME = "I am Test1";
    public void print();
}

* 이름 : Test2

//두번째 인터페이스
public interface Test2 {
    public final String NAME = "I am Test2";
    public void print();
}

 

해당 2개의 인터페이스를 상속받아 봅니다.

* 이름 : TestMain

public class TestMain implements Test1, Test2 {

    public static void main(String[] args) {

    }

    @Override
    public void print() {

    }

}

 

여기까지는 별로 어려울게 없는 내용 입니다.

Test1과 Test2의 인터페이스에서 메소드 이름이 print 동일 하지만 상속 받는 TestMain 클래스 입장에서는 몸통이 없는(내용이 없는) 메소드 이므로 따로 구분없이 Override 1개만으로도 상속이 가능 합니다.

 

다음으로 Test1에서의 NAME이라는 상수와, Test2에서의 NAME이라는 상수가 서로 겹치는 것을 볼 수 있습니다.

아무 생각 없이 겹치는 상수를 가져오게 되면 문제가 발생 합니다.

이 NAME이 누구의 것 입니까??

 

TestMain 클래스 입장에서는 저 NAME이 누구의 것 인지 알 수 없기 때문에 컴파일에서의 오류가 발생하여 버립니다.

그러므로 이럴 때는 누구껀지 아래처럼 명시를 해 주어야 합니다.

* 이름 : TestMain

public class TestMain implements Test1, Test2 {

    public static void main(String[] args) {
        //System.out.println(NAME);  //누구껀지 몰라 오류가 발생!!!
        System.out.println(Test1.NAME);
        System.out.println(Test2.NAME);
    }

    @Override
    public void print() {

    }

}

 

여기까지가 Java 7까지 인터페이스를 상속받을 때 주의해야되는 점 이었습니다.

 

 

#자바 8부터 인터페이스 상속시 유의 사항 ─

 

 

그런데 자바 8에서는 default(디폴트)라는 기본형태의 제어자가 생겼습니다.

인터페이스에서 default가 붙여있는 메소드는 머리 이외의 몸통이 존재하는 메소드를 의미 합니다.

* 이름 : Test1

//첫번째 인터페이스
public interface Test1 {
    public final String NAME = "I am Test1";
    public void print();
    default public void print2() {
        System.out.println(NAME);
    }
}

 

위에서 보이는 Test1에서의 메소드 중 print2라는 메소드는 머리 이외의 몸통이 존재 합니다.

default 메소드는 내용이 만들어진 형태 그대로도 사용 가능하며, 오버라이드하여 변경도 가능 합니다.

단순하게 상속받은 메소드를 사용하려면 아래 모습처럼 일반 메소드를 호출 하듯이 해 주면 됩니다.

* 이름 : TestMain

public class TestMain implements Test1, Test2 {

    public static void main(String[] args) {
        TestMain mm = new TestMain();
        mm.print2();
    }

    @Override
    public void print() {

    }

}

잘 나오네요~

 

print 메소드의 내용을 변경 한 다면 아래처럼 Override를 통해서 메소드 내용을 변경하여 주면 됩니다.

* 이름 : TestMain

public class TestMain implements Test1, Test2 {

    public static void main(String[] args) {
        TestMain mm = new TestMain();
        mm.print2();
    }

    @Override
    public void print() {

    }

    @Override
    public void print2() {
        //Test1.super.print2();  //상속받은 메소드 사용 안합니다.
        System.out.println("TestMain으로 변경!");
    }
}

 

일반적으로 인터페이스에서 default 제어자가 붙은 메소드는 일반적으로 오버라이드 하지 않고 그대로를 사용하고는 합니다.

default를 붙였다는 의미는 해당 Interface를 만든 사람이 "메소드 자체의 기능이 잘 만들어 놓았으니 그냥 쓰세요~" 처럼 권유하는 경우가 많습니다.

간단한 예로는 Collection.toArray(), Comparator.comparing() 등을 볼 수 있습니다.

* 물론 경우에 따라서 상속받아서 변경해서 쓰기도 할 것 입니다. ^^

 

 

만약 Test1과 Test2 인터페이스가 default 메소드 이름이 같으면 역시나 모호한 상태라고 오류가 발생합니다.

마찬가지로 컴파일전에서 오류가 발생하는데, 친절한 개발도구님(?)들 께서 오류에 대한 해결방안을 제시하여 줍니다.

이름이 같은 디폴트 메소드때문에 햇갈려 하고 있습니다.

 

오버라이드를 통해서 누구의 것을 사용할 지 알려주도록 합니다.

오버라이드!

 

#자바 11부터 인터페이스 상속시 유의 사항 ─

 

 

자바 11에 와서는 private 접근제어자가 있는 메소드가 인터페이스에서 사용 할 수 있게 되었습니다.

private 메소드는 일반적인 class에서 사용하는 기능과 동일 합니다.

그러므로 private 메소드는 인터페이스 내부에서만 사용 가능 하므로 이름이 겹치더라도 문제되는 것은 없습니다.

이름이 겹치는 data 메소드가 존재합니다. 당연히 오류는 발생하지 않습니다.

 

자바 7 까지의 인터페이스는 몸통이 없는 메소드나 상수만 가질 수 있었다면,

자바 8 부터의 인터페이스는 디폴트(default) 메소드, 자바 11부터는 private 메소드 등 다양한 기능이 생겨나는 것을 볼 수 있습니다.

자바에서 버전이 올라감에 따라 인터페이스의 기능이 변경된 것을 볼 수 있었습니다!

궁금한점이나 틀린부분은 언제든지 알려주세요!

 

반응형
* 위 에니메이션은 Html의 캔버스(canvas)기반으로 동작하는 기능 입니다. Html 캔버스 튜토리얼 도 한번 살펴보세요~ :)
* 직접 만든 Html 캔버스 애니메이션 도 한번 살펴보세요~ :)

댓글