java

자바 8 - interface 2

Jan 29, 2020

인터페이스의 예

목차

1. 인터페이스의 예
2. Comparable 인터페이스
3. Comparator 인터페이스
4. Runnable 인터페이스
5. 사용자 인터페이스 콜백

1. 인터페이스의 예

언뜻 보면 인터페이스는 많은 일을 하는 것 같지 않다. 그저 클래스가 구현을 약속하는 메서드의 집합이다. 하지만 중요하다. 자주 사용하는 네 가지 인터페이스로 인터페이스의 중요성을 살펴본다. 네 가지 인터페이스는 표준 자바 라이브러리에 들어 있는 것들이다.

2. Comparable 인터페이스

클래스가 자신이 갖고 있는 객체를 정렬하려면 Comparable 인터페이스를 구현해야 한다. 문자열대 문자열, 인스턴스 대 인스턴스로 비교해야 하므로 타입 파라미터를 받는다.

Comparable 인터페이스는 객체 간에 일반적인 정렬이 필요할 때 정렬의 기준을 정하는 compareTo 메서드를 확장해서 정의한다.

public interface Comparable<T> {
    int compareTo(T other);
}
x.compareTo(y);

    Employee emp1 = new Employee(1, "mike", 100.1);
    Employee emp2 = new Employee(2, "john", 123.45);
    Employee emp3 = new Employee(3, "seungui", 9.9);
    Employee emp4 = new Employee(4, "changStar", 20000);

    List<Employee> empList = new ArrayList<>();
    empList.add(emp1);
    empList.add(emp2);
    empList.add(emp3);
    empList.add(emp4);
    System.out.println("리스트에 넣은 순서대로");
    System.out.println(empList);
    System.out.println("compareTo 메소드에 정한 순서로");
    empList.sort(empList);
    System.out.println(empList);

compareTo 메서드는 정수 값을 반환한다.

양수를 반환하면 x가 y다음에 온다. 음수 값이 오면 y가 x다음에 온다. x와 y가 같으면 반환값이 0이다.

public class Employee implements Comparable<Employee> {

    ...

    @Override
    public int compareTo(Employee other) {
        return getId() - other.getId();
    }
}

정수가 음수일 때 두 정수의 차이를 반환하면 메서드가 제대로 동작하지 않는다. 이럴 때는 Integer.compare 메서드를 사용한다.

부동소수점 값을 비교할 때는 정적 메서드 Double.compare를 사용해야 한다.

@Override
    public int compareTo(Employee other) {
        return Double.compare(getSalary(), other.getSalary());
    }



3. Comparator 인터페이스

문자열을 사전 순서가 아닌 증가하는 길이 순서로 비교한다고 하자. String 클래스로는 compareTo 메서드를 다른 방법으로 구현하게 만들 수 없다. String 클래스는 우리가 소유한 클래스가 아니므로 수정할 수 없다.

Comparator 인터페이스는 객체 간의 특정한 정렬이 필요할 때, compare 메서드를 확장하여 구현한다. Compareble과 공통점은 정렬의 기준을 정한다는 것이고 차이점은 정렬 기준이 일반적이냐 특정하냐의 차이다.

public interface Comparator<T> {
    int compare(T first, T second);
}

Comparator를 구현한 클래스를 사용하거나 익명 클래스를 만들어서 사용한다.

public class LengthComparator implements Comparator<String> {
    @Override
    public int compare(String first, String second) {
        return first.length() - second.length();
    }
}

// main.java
LengthComparator lengthComparator = new LengthComparator();
String word1 = "show me the moeny";
String word2 = "power overwhelming";
if(lengthComparator.compare(word1, word2) > 0) {
    System.out.println("word1's length is Long");
} else {
    System.out.println("hmm");
}
//익명의 Comparator를 만들기
Comparator<Employee> nameLengthComparator = new Comparator<Employee>() {
    @Override
    public int compare(Employee o1, Employee o2) {
        return o2.getName().length() - o1.getName().length();
    }
};

// 람다 표현식으로 줄이면..
// empList.sort(empList, (o1, o2) -> o2.getName().length() - o1.getName().length());

empList.sort(empList, nameLengthComparator);
System.out.println(empList);



4. Runnable 인터페이스

모든 프로세서가 멀티 코어를 장착하면서 모든 코어가 바쁘게 작업하게 되었따. 아마 특정 작업을 별도의 스레드에서 실행하거나 실행 스레드 풀에 넣으려고 할 것이다. 이렇테 테스크를 정의하려면 Runnable 인터페이스를 구현해야 한다. Runnable 인터페이스는 메서드를 하나만 갖는다.

public class HelloTask implements Runnable {

    @Override
    public void run() {
        for(int i = 1; i < 1000; i++) {
            System.out.println("Hello World~~!!!");
        }
    }
}

테스크를 새로운 스레드에서 실행하려면 Runnable로부터 스레드를 생성하고 해당 스레드를 시작한다.

HelloTask helloTask = new HelloTask();
Thread thread = new Thread(helloTask);
thread.start();

이제 run 메서드는 별도의 스레드에서 실행되며, 현재 스레드에서는 다른 작업을 계속할 수 있다.

5. 사용자 인터페이스 콜백

GUI에서는 사용자가 버튼 클릭, 메뉴 옵션 선택, 슬라이더 드래그 등의 액션을 했을 때 수행될 액션을 지정해야 한다. 수행될 액션을 보통 콜백이라 하는데, 사용자가 어떤 액션을 취했을 때 역으로 일부 코드가 호출되기 때문이다.

자바기반 GUI 콜백 라이브러리에서는 콜백 인터페이스를 사용한다. JavaFX에서는 이벤트를 보고할 때 다음과 같은 인터페이스를 사용한다.

public interface EventHandler<T> {
    void handle(T event);
}

여기서 T는 버튼 클릭에 해당하는 ActionEvent처럼 보고할 이벤트의 타입이다.

public class CancleAction implements EventHandler<ActionEvent> {

    @Override
    public void handle(ActionEvent event) {
        System.out.println("action!");
    }
}