덕개

[Java - Basic] 인터페이스, default, 다형성

Always2024 2024. 4. 27. 15:26

1. Java Interface

Java에서 인터페이스는 다중 상속을 지원하고 코드의 유연성과 확장성을 제공한다.

인터페이스를 구현하는 클래스들은 인터페이스가 정의한 메서드를 모두 구현해야 한다.

 

이를 통해 코드의 일관성을 유지하고, 서로 다른 클래스 간 호환성을 보장할 수 있다.

 

개발자들은 개발을 하기 전 서로 업무를 구분한다.

업무가 연계되는 부분이 생기면서 만들어지지 않은 부분은 서로 참조하기 위한 것인데, 나중에 호출하면 알아서 쓸 수 있게 하도록 미리 정의하는것이다.

 

인터페이스에서 정의하는 method는 추상클래스처럼 구현체는 없다.

그냥 method와 parameter 정도만 정의한다.

 

public class InterTest01 {

    public static void main(String[] args) {
    
    	//interface 에 선언된 멤버필드는 묵시적으로 상수값으로 정의된다.
        System.out.println(ICoffeeMachine.volume); 

        ICoffeeMachine americano = new Americano();
        americano.newDrink("아메리카노", 5);
    }
}


class Americano implements ICoffeeMachine {

    @Override
    public void newDrink(String name, int unitPrice) {
        System.out.println(name + "을(를) 제조합니다.");
        System.out.println("용량은 " + volume + "ml 입니다.");
        System.out.println("가격은 " + unitPrice * volume + " 원 입니다.");
    }
}

interface ICoffeeMachine {
    int volume = 330; //static final int volume;
    void newDrink(String name, int unitPrice);

}

 

위 소스는, ICoffeMachine 인터페이스를 구현한 Americano 클래스이다.

인터페이스에서 선언한 newDrink() 추상메서드는 Americano 클래스에서 반드시 구현해야 한다.

원래 인터페이스에서 newDrink() 앞에는 abstract가 붙는데 이건 생략된 것이다. 마찬가지로 인터페이스 ICoffeMachine 앞에서 abstract가 생략되어있다. (붙여도 상관없다)

 

main Americano 의 구현체인 ICoffeMachine를 클래스명으로 지정하고 americano 의 인스턴스를 new Americano() 로 생성하는 것도 가능하다.

위 소스에선 의미없긴 하지만, 이를 다형성이라고 한다.

 

참고로 Interface 에서 선언된 필드는 묵시적으로 정적 상수값으로 정의된다.

 

2. default

그런데, 만약 개발시간이 흐르면서 인터페이스의 구현체가 많이 생겨났는데 인터페이스에 메서드가 추가된다면 모든 구현체마다 메서드를 추가해야 하는 현상이 발생한다.

1~2년 이상 운영되어온 프로젝트의 경우 수십개의 구현체가 있을 수도 잇다.

이럴 때, default 메서드를 추가할 수 있다.

default 는 JDK 1.8에서 추가되었는데 재정의를 하지 않아도 그대로 구현체를 상속받을 수 있는 method이다.

 

아래처럼 간단하게 소스를 추가하면 인스턴스에서 바로 사용할 수 있다.

interface ICoffeeMachine {
    int volume = 330; //static final int volume;
    void newDrink(String name, int unitPrice);


    String brandName = "StarBucks";
    
    default String getBrandName() {
        return brandName;
    }

}

 

이렇게 메서드 앞에 default를 붙여주면 구현체에서 이를 재정의하지 않아도 인스턴스에서 바로 사용할 수 있다.

public class InterTest01 {

    public static void main(String[] args) {
    	//interface 에 선언된 멤버필드는 묵시적으로 상수값으로 정의된다.
        System.out.println(ICoffeeMachine.volume); 

        ICoffeeMachine americano = new Americano();
        americano.newDrink("아메리카노", 5);

        System.out.println(americano.getBrandName());
    }
}

 

 

3. 다형성

아래의 소스에서 인터페이스와 구현체를 확인해보자.

public class InterTest02 {

    public static void main(String[] args) {
        Person1 p1 = new Person1();
        Person2 p2 = new Person2();
        Person3 p3 = new Person3();
        
        p1.study();
        p2.teach();
        
        p3.study();
        p3.teach();
        
    }
}


interface Student{
    void study();
}

interface Teacher{
    void teach();
}


class Person1 implements Student {

    @Override
    public void study() {
        System.out.println("사람1이 공부한다");
    }
}

class Person2 implements Teacher {

    @Override
    public void teach() {
        System.out.println("사람2가 가르친다.");
    }
}

class Person3 implements Student, Teacher {


    @Override
    public void study() {
        System.out.println("사람3이 공부한다.");
    }

    @Override
    public void teach() {
        System.out.println("사람3이 가르친다.");
    }
}

 

Person 1,2,3 이 있는데 각각 Student, Teacher 를 구현하였는데 Person3 은 인터페이스의 다중상속 속성으로 인해 둘 다 구현하였다.

위 소스에서 생성된 인스턴스 중 p1, p2 는 단일상속이라서 문제가 없다.

다중상속을 받고있는 p3 의 자료형이 아래처럼 Student로 바뀌면 어떻게 될까?

public class InterTest02 {

    public static void main(String[] args) {
        Person1 p1 = new Person1();
        Person2 p2 = new Person2();
        Student p3 = new Person3();

        p1.study();
        p2.teach();

        p3.study();
        p3.teach(); //에러

    }
}

Student 인터페이스에는 teach가 정의되지 않았기 때문에 p3.teach(); 에서 에러가 발생한다.

 

즉, 다형성은 객체지향 프로그래밍에서 한 가지 기능이나 행위를 다양한 방식으로 수행할 수 있는 능력을 의미한다.

이는 코드의 유연성과 확장성을 높이기 위함인데, 사람에 따라 선생님도 있고 학생도 있고 기본 동작이 있지만 각자의 특징에 따라 다른 행동을 할 수 있기 때문이다.

이런 다형성은 코드의 재사용성과 유지보수성을 향상시키는 데 큰 기여를 한다.