자바 인터페이스

KangMyungJoe·2021년 1월 7일
0

java_study

목록 보기
7/8
post-thumbnail

백기선님과 함께하는 Java-Study 8주차

8주차 과제: 자바 인터페이스
목표: 자바의 인터페이스에 대해 학습하기

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

0. 인터페이스란?

인터페이스란, 자바가 가지고 있는 제약 중 하나인 다중 상속이 불가능 한 제약조건을 해결하기 위해 도입된 개념으로, 각 클래스 사이에서 클래스를 엮어주는 역할을 하며 추상 메소드를 선언함으로써 클래스 간의 통일성을 부여한다.

인터페이스를 사용하는 이유는 무엇일까?

  • 인터페이스를 통해 각 클래스들을 연결하고 통일성을 부여하며, 기능을 구현하는 데 집중할 수 있도록 한다.
  • 선언부와 구현부를 구별하는 데 도움을 준다.
  • 개발자들의 의사소통에 도움을 준다.

1. 인터페이스 정의하는 방법

인터페이스를 정의할 때에는, 2가지 특성을 고려하여 코드를 작성해야 한다.

  1. body부분이 존재하지 않는 abstract method만 선언할 것
  2. 한번 선언되면 값이 변하지 않는 상수만 선언할 것

다음은 인터페이스의 예다.

public interface Pencil {

    public int PENCIL_LENGTH = 15;
    public String PENCIL_BRAND = "JEDO";

    public void writeEnglish(String englishSentence);
    public void writeKorean(String hangulSentence);
    public void broke();
}


public class Student implements Pencil{
    public static void main(String[] args) {
        System.out.println("this is student class");
    }
    
    @Override
    public void writeEnglish(String englishSentence) {
        System.out.println("this is English sentence");
    }

    @Override
    public void writeKorean(String hangulSentence) {
        System.out.println("this is Korean sentence");
    }

    @Override
    public void broke() {
        System.out.println("Ouch! it's broken");
    }
}

Pencil 이라는 인터페이스를 선언하고, Student 클래스에서 이를 implements 하여 인터페이스에서 선언한 추상 메소드들을 사용할 수 있도록 했다.


2. 인터페이스 구현하는 방법

인터페이스를 구현하기 위해서, 먼저 클래스에서 implements 예약어를 사용해야 한다. 앞서 1장에서 예시로 보여준 Student 클래스에서도 사용했다.

  • (인터페이스는 클래스와는 달리 여러 개도 implements할 수 있다)

인터페이스에 선언된 메소드들을 override 하지 않으면, 해당 클래스는 추상 클래스가 된다.

public interface Pencil {

    public int PENCIL_LENGTH = 15;
    public String PENCIL_BRAND = "JEDO";

    public void writeEnglish(String englishSentence);
    public void writeKorean(String hangulSentence);
    public void broke();
}


public class Student implements Pencil{
    public static void main(String[] args) {
        System.out.println("this is student class");
    }
    
    @Override
    public void writeEnglish(String englishSentence) {
        System.out.println("this is English sentence");
    }

    @Override
    public void writeKorean(String hangulSentence) {
        System.out.println("this is Korean sentence");
    }

    @Override
    public void broke() {
        System.out.println("Ouch! it's broken");
    }
}

예제에서도 Student 클래스는 Pencil 인터페이스에서 선언한 모든 메소드들을 override하여 사용하는 것을 확인할 수 있다. 만약, 1개 라도 override 하지 않는다면 에러가 발생한다.


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

인터페이스 레퍼런스를 통해 구현체를 사용하는 방법은 실 예제를 보며 익혀보자.

다음과 같이 Car 인터페이스가 존재하고, Morning Sonata 클래스가 이를 implements 한다.

public interface Car {
    public void speakCarName();
    public void speakCarBrand();
}


public class Morning implements Car{
    @Override
    public void speakCarName() {
        System.out.println("I am Morning");
    }

    @Override
    public void speakCarBrand() {
        System.out.println("I'm in Kia!");
    }
}

public class Sonata implements Car{
    @Override
    public void speakCarName() {
        System.out.println("I am Sonata");
    }

    @Override
    public void speakCarBrand() {
        System.out.println("I'm in Hyundai!");
    }
}

public class CarExam {
    public static void main(String[] args) {
        Morning morning = new Morning();
        Sonata sonata = new Sonata();
        
        sonata.speakCarName();
        sonata.speakCarBrand();   

        morning.speakCarName();
        morning.speakCarBrand();
    }
}


// 결과 값: 

I am Sonata
I'm in Hyundai!
I am Morning
I'm in Kia!

Car 인터페이스에서 선언한 speakCarName() speakCarBrand() 메소드를 override하여 정상적으로 사용함을 확인할 수 있다.

다음과 같이 CarExam 클래스의 내용을 조금 변경했을 때
인터페이스 레퍼런스를 통해 구현체를 사용하는 것을 확인할 수 있다. (Car)

public class CarExam {
    public static void main(String[] args) {
        Car morning = new Morning();
        Car sonata = new Sonata();

        showBrand(morning);
        showBrand(sonata);

    }
    public static void showBrand(Car car) {
        car.speakCarBrand();
    }
}


// 결과 값: 
I'm in Kia
I'm in Hyundai!

4. 인터페이스 상속

인터페이스 상속이란, 자식 클래스가 부모 클래스를 상속받는 것과 비슷하게 작동한다. (클래스와 마찬가지로 extends 예약어를 사용한다)

부모 인터페이스에 선언된 추상 메소드를 자식 인터페이스에서 상속받은 뒤, 새로운 추상 메소드나 상수를 추가한다.

예제는 다음과 같다.

public interface A {
    int LENGTH = 10;

    public void speak();
}

public interface B extends A{
    @Override
    void speak();

    void run();
     int LENGTH = 20;

}

public class InheritanceExam implements B{
    @Override
    public void speak() {
        System.out.println("Hello!!");
    }

    @Override
    public void run() {
        System.out.println("running!!!!");
    }

    public static void main(String[] args) {
        A a = new InheritanceExam();
        B b = new InheritanceExam();

        System.out.println(a.LENGTH);
        System.out.println(b.LENGTH);
    }
    
    
// 결과 값: 

10
20

예제에서 보는 것 처럼 InheritanceExam 클래스는 A 인터페이스를 implements 하지 않았지만, B 인터페이스가 A 인터페이스를 상속받았기 때문에 A 인터페이스에 존재하는 speak() 까지 override 해야 한다.


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

인터페이스의 기본 메소드란, 자바 8이 등장하며 새롭게 정의된 인터페이스로 선언과 동시에 구현할 수 있는 메소드를 말한다.

(다이아몬드 문제가 발생할 수 있으니 명확히 작성해야 한다)

public interface Animal {
    public void speak();

    default void findMyFriend(String friendName) {
        System.out.println("Where is " + friendName+ "?") ;
    }
}

public class Cat implements Animal{
    @Override
    public void speak() {
        System.out.println("Meow!");
    }

    public static void main(String[] args) {
        Animal cat = new Cat();

        cat.findMyFriend("Dog");
    }
}

// 결과 값:

Where is Dog?

위 예제처럼 인터페이스에서 구현부까지 작성할 수 있도록 해주는 개념이다.

  • Object 클래스가 제공하는 메소드들은 기본 메소드로써 사용이 불가하다.

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

인터페이스의 static 메소드란, 앞서 5장에서 설명한 default 메소드처럼 자바 8에서 새롭게 등장한 개념으로, override가 불가능한 메소드를 뜻한다.

public interface A {
    public void speak();

    public static void run() {
        System.out.println("run!!!!!");
    }
}


public class Exam implements A{
    @Override
    public void speak() {
        System.out.println("Hello");
    }

    public void run() {
        System.out.println("what is this?");
    }

    public static void main(String[] args) {
        A a = new Exam();

//       a.run();  <-- 에러 발생
         A.run();
    }
}


// 결과 값:

run!!!!!
  • interface 이름.static 메소드 이름 의 형식으로 접근해야 사용 가능하다.

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

인터페이스의 private 메소드란, 자바 9에서 새롭게 등장한 개념으로, 자바 8에서 등장한 default, static 메소드가 등장한 후의 메소드들의 관리에 사용한다.

public interface I {
    private static String speak() {
        return "Hello!";
    }

    private static void run() {
        System.out.println("Run!!!!");
    }

    public static void speakMyName(String name) {
        System.out.println(speak() + " My name is "+ name + "!");
    }
}


public class Exam implements I {
    public static void main(String[] args) {
        I i = new Exam();

//      i.run();
//      i.speak();        <-- 둘 다 에러 발생

        I.speakMyName("GGOB2");
    }
}


// 결과 값:

Hello! My name is GGOB2!

다른 default, static 메소드처럼 구현부를 작성할 수 있으며 static 키워드를 붙힐 수 있다.


참고

참고1
참고2
참고3
참고4
참고5

profile
소통을 잘하는 개발자가 되고 싶습니다.

0개의 댓글