공부/Java

일단 마시고 본다. (인터페이스 default와 static)

오잎 클로버 2022. 1. 5. 22:10
728x90

제가 자바를 독학으로 3년정도하였는 데도 역시 가끔 까먹는 경우가 발생하여

이를 계속 이해하고 기억하고자 글을 쓰게 되었습니다.

 

제목이 일단 마시고 본다. 의 의미는 자바의 유래로 말장난을 한 것입니다.

(자바 언어는 자바 커피에서 유래된 이름입니다. 그래서 일단 자바를 마시고 나서 이해를 하자.

즉, 일단 개발해보면서 차차 이해해가자 라는 의미입니다.)

 

먼저 다른 중요한 것들은 다 빼먹고 인터페이스부터 시작하는 이유는 

인터페이스의 default 메소드와 static 메소드 때문에 쓰기 시작했습니다.

 

일단 둘 다 인터페이스에서 메소드를 정의를 하여 이를 그대로 사용할 수 있다는 공통점이 있지만

자바는 최적화 언어의 대명사처럼 굳이 똑같은 기능들 2개나 제공해주지않았을 거라는 믿음에서 

천천히 알아보았습니다.

 

일단 좋은 예시는 아니지만 예시를 하나 준비해왔습니다.

예시는 사람입니다.

Human이라는 인터페이스를 생성해서 몇가지를 정의해주었습니다.

public interface Human {

    public void eat();

    public void eat(String food);
    
    default void sleep() {
        System.out.println("잠 자기");
    }

    public static void breathe() {
        System.out.println("숨 쉬기");
    }

}

public은 굳이 안 붙여도 되지만 그냥 붙임 (묵시적으로 존재함)

eat은 먹는 메소드입니다.

eat(food)는 어떤 것을 먹는 지 정해줍니다.

sleep은 자는 메소드입니다.

breathe는 숨을 쉬는 메소드입니다.

 

그리고 이런 차이점들을 조금이라도 이해하기 위해

3개의 클래스를 생성했습니다.

Man, Woman. Baby 입니다.

셋 다 Human 이라는 인터페이스를 상속했습니다.

 Man은

public class Man implements Human {

    @Override
    public void eat() {
        System.out.println("깨작깨작 먹는 중");
    }

    @Override
    public void eat(String food) {
        System.out.printf("%s를 ", food);
        eat();
    }

    @Override
    public void sleep() {
        System.out.println("안 잔다.");
    }

    public void breathe() {
        Human.breathe();
    }

}

뭘 먹든 깨짝깨짝 먹고

잠 따위는 안 잡니다.

 

Woman은

public class Woman implements Human {

    @Override
    public void eat() {
        System.out.println("먹으면서 후회합니다.");
    }

    @Override
    public void eat(String food) {
        System.out.printf("%s를 ", food);
        eat();
    }

    public void breathe() {
        Human.breathe();
    }

}

뭘 먹든 먹으면서 후회합니다.

그리고 Man 클래스와 달리 sleep을 재정의(오버라이딩)하지 않았습니다.

 

마지막으로 Baby는

public class Baby implements Human {

    @Override
    public void eat() {
        System.out.println("조용히 먹습니다.");
    }

    @Override
    public void eat(String food) {
        System.out.printf("%s를 ", food);
        eat();
    }
    
    public void breathe() {
        Human.breathe();
    }
    
}

Woman 클래스와 가장 흡사합니다.

이로 인해 알 수 있는 점은

인터페이스의 메소드 중 default 메소드의 경우, 재정의를 할 수도 있고 하지 않을 수 도 있다는 점이고

 static 메소드는 재정의가 불가능하며, Human 이라는 인터페이스에서 직접 호출해야합니다.

 

public class Main {

    public static void main(String[] args) {
        Man man = new Man();
        man.breathe();
        man.eat("피자");
        man.sleep();

        Woman woman = new Woman();
        woman.breathe();
        woman.eat("치킨");
        woman.sleep();

        Baby baby = new Baby();
        baby.breathe();
        baby.eat("자두");
        baby.sleep();
    }
}

실행을 해보면

이런식으로 나옵니다.

 

오늘 요약)

인터페이스의 static 메소드는 재정의가 불가능하며, 인터페이스 스스로 호출해서 사용해야한다.

반면 default 메소드는 재정의가 가능하며, 필수가 아니다.

 

이상입니다.