45일차 (2) - java (내부 클래스, 익명 클래스, 람다)

Yohan·2024년 4월 24일
0

코딩기록

목록 보기
66/156
post-custom-banner

내부 클래스(중첩 클래스) & 익명 클래스

  • 보통 인터페이스를 통해 추상 메서드를 만들고 클래스를 만들어 인터페이스를 구현해서 사용한다.
// 람다를 사용할 수 있는 인터페이스인지 점검
@FunctionalInterface
public interface Calculator {

    // 계산 기능 명세
    int operate(int n1, int n2);
}


public class AddCalculator implements Calculator {
    @Override
    public int operate(int n1, int n2) {
        return n1 + n2;
    }
}
  • 하지만 Main메서드에서만 필요하다거나 딱 한개의 메서드만 필요하다면 이렇게 불필요하게 클래스를 만들면 불편하지 않을까? 그래서 나온 개념이 내부 클래스와 익명 클래스이다.

내부 클래스

  • 위 예시에 연장선으로 뺄셈 계산기를 만들려고하는데 실행할 때 Main 클래스 안에서만 사용하고 외부에서는 더이상 쓰지 않을 것 같을 때 내부 클래스를 사용한다.
  • 위치는 Main 클래스와 Main 메서드 사이
  • 자식 클래스를 생성할 때와 똑같이 인터페이스를 구현해서 오버라이딩해서 사용한다.
public class Main {

    // 내부 클래스 (중첩 클래스)
    public static class SubCalculator implements Calculator {

        @Override
        public int operate(int n1, int n2) {
            return n1 - n2;
        }
    }

    public static void main(String[] args) {

        Calculator cal;
        cal = new AddCalculator();
        
        // 덧셈
        int r1 = cal.operate(10, 20);
        System.out.println("r1 = " + r1);

		// 뺄셈
        cal = new SubCalculator();
        int r2 = cal.operate(50, 27);
        System.out.println("r2 = " + r2);

익명 클래스

  • 이름이 없는 클래스
  • 클래스를 통해 객체 생성을 할 건데 일회용성으로 사용하는 클래스다. (재활용 X)
  • main 메서드 안에서 생성해서 바로 일회용으로 사용한다.
  • 위 예시에 이어서 곱셈을 익명 클래스로 만들어 보겠다.
cal = new Calculator() {
            @Override
            public int operate(int n1, int n2) {
                return n1 * n2;
            }
        };

        int r3 = cal.operate(10, 4);
        System.out.println("r3 = " + r3);
  • 위 코드처럼 똑같이 오버라이딩해서 사용하는 것을 볼 수 있다. 이렇게 사용하면 일회성으로 곱셈을 만들어 낼 수 있다.

익명 클래스 -> 람다 변환

  • 익명 클래스는 람다식으로 변환이 가능하다.
  • 단, 반드시 인터페이스 안의 추상메서드가 1개여야 람다로의 변환이 가능하다.
  • 추상메서드가 1개인지 확인 가능하게 해주는 어노테이션이 있다. @FunctionalInterface 이다. 인터페이스 위에 저 어노테이션을 써놓고 추상메서드가 1개가 넘어가게되면 빨갛게 에러가 뜨는 것을 볼 수 있다.
		cal = (n1, n2) -> n1 * n2;
  • 놀랍게도 위 곱셈식과 같은 식이다. Calculator가 operate 메서드를 가지고 있는 것을 알고 있고 {}와 return 생략이 가능한 점 등을 포함해서 저렇게 간단하게 나타낼 수 있다.
// 람다를 사용할 수 있는 인터페이스인지 점검
@FunctionalInterface
public interface Restaurant {

    void cook();
}

// FrenchRestaurant에서 인터페이스 구현
public class FrenchRestaurant implements Restaurant {

    @Override
    public void cook() {
        System.out.println("프랑스 요리를 합니다.");
    }

}

// main

		Restaurant fr = new FrenchRestaurant();

        // 익명 클래스 (레스토랑을 1개 지점만 만들고 말꺼면 일회용인 익명클래스로 만들어라)
        Restaurant japaneseRestaurant = new Restaurant() {
            @Override
            public void cook() {
                System.out.println("일식 요리를 합니다.");
            }

        };

        Restaurant italian = () -> System.out.println("이탈리아 요리를 합니다.");


        fr.cook(); // 프랑스 요리를 합니다.
        japaneseRestaurant.cook(); // 일식 요리를 합니다.
        italian.cook(); // 이탈리아 요리를 합니다.
  • 위 예시를 하나 더 보게되면
    Restaurant 인터페이스를 FrenchRestaurant에서 구현하여 나타낼 수도 있고
    익명 클래스를 활용하여 일회성있게 main 메서드에서 직접 구현할 수 있다. 또한 인터페이스에서 추상메서드가 1개 이기때문에 람다로의 변환해서 구현도 가능하다.
profile
백엔드 개발자
post-custom-banner

0개의 댓글