[6/7 TIL] JAVA(인터페이스, 함수형 인터페이스, 인터페이스 생성)

yumyeonghan·2023년 6월 9일
0
post-custom-banner

🍃프로그래머스 백엔드 데브코스 4기 교육과정을 듣고 정리한 글입니다.🍃

Interface

  • 구현을 강제합니다.
    • 클래스가 인터페이스를 구현한다면, 해당 클래스는 인터페이스에 정의된 모든 메서드를 구현해야 합니다.
  • 다형성을 제공합니다.
    • 인터페이스를 구현한 다양한 클래스들은 동일한 인터페이스 타입으로 다룰 수 있습니다.
  • 의존성을 역전시킵니다.
    • 클래스가 인터페이스만을 참조하여 작업을 수행하면, 의존성이 역전될 수 있습니다.

Interface 개선

default 메소드

// 인터페이스
interface Animal {
    void makeSound();

    // 디폴트 메소드
    default void eat() {
        System.out.println("Animal is eating");
    }
}

// 어댑터 클래스
class AnimalAdapter implements Animal {
    @Override
    public void makeSound() {
        // 구현하지 않음
    }
}

// 구체적인 구현 클래스
class Dog implements Animal {
    @Override
    public void makeSound() {
        System.out.println("Dog is barking");
    }
  
    // eat() 메소드는 이미 Animal 인터페이스의 디폴트 구현을 가지므로 오버라이딩하지 않아도 됨
}

public class Main {
    public static void main(String[] args) {
        Animal dog = new Dog();
        dog.makeSound();  // 출력: "Dog is barking"
        dog.eat();  // 출력: "Animal is eating"
      
        AnimalAdapter animalAdapter = new AnimalAdapter();
        animalAdapter.makeSound();  // 출력: 없음
        animalAdapter.eat();  // 출력: "Animal is eating"
    }
}
  • 자바 8부터 인터페이스 내에 직접 구현을 제공할 수 있습니다.
  • 구현체는 기본 구현을 사용하거나 오버라이드 하여 사용할 수 있습니다.
  • 필요한 메서드만 오버라이드 해서 사용하고 싶을 때 사용하는 Adapter 패턴의 역할을 해줍니다.
  • 기존의 구현체의 수정 없이 인터페이스 기능 확장이 가능합니다.

static 메소드

// 인터페이스
interface MathOperation {
    static int add(int a, int b) {
        return a + b;
    }

    static int subtract(int a, int b) {
        return a - b;
    }
}

public class Main {
    public static void main(String[] args) {
        int num1 = 10;
        int num2 = 5;

        int sum = MathOperation.add(num1, num2);
        int difference = MathOperation.subtract(num1, num2);

        System.out.println("Sum: " + sum);  // 출력: Sum: 15
        System.out.println("Difference: " + difference);  // 출력: Difference: 5
    }
}
  • 자바 8부터 인터페이스 내에 정적 메소드를 가질 수 있습니다.
  • 인터페이스 이름을 통해 정적 메소드를 직접 출력할 수 있는 함수 제공자 역할을 수행할 수 있게 됩니다.

Functional Interface

@FunctionalInterface
interface MathOperation {
    int operate(int a, int b);
}

public class Main {
    public static void main(String[] args) {
        MathOperation addition = (a, b) -> a + b;
        System.out.println("Addition: " + addition.operate(5, 3));  // 출력: Addition: 8

        MathOperation subtraction = (a, b) -> a - b;
        System.out.println("Subtraction: " + subtraction.operate(5, 3));  // 출력: Subtraction: 2
    }
}
  • 함수형 인터페이스는 반드시 추상 메소드(함수)를 하나만 가져야 합니다.
  • default, static 메소드는 여러 개 있어도 상관없습니다.
  • 인터페이스에 @FunctionalInterface 어노테이션을 설정합니다.

java.util.funtion

Java에서 기본으로 제공하는 functional Interface

Predicate<T>

Predicate<String> isLengthGreaterThan5 = str -> str.length() > 5;
boolean result = isLengthGreaterThan5.test("Hello, World!");
System.out.println(result);  // 출력: true
  • 주어진 조건에 대해 참 또는 거짓을 반환하는 함수입니다.
  • 예시: 문자열의 길이가 5보다 큰지 확인하는 Predicate

Function<T, R>

Function<Integer, String> convertToString = num -> String.valueOf(num);
String strNum = convertToString.apply(42);
System.out.println(strNum);  // 출력: "42"
  • 입력을 받아 변환한 결과를 반환하는 함수입니다.
  • 예시: 정수를 문자열로 변환하는 Function

Consumer<T>

Consumer<String> printMessage = message -> System.out.println(message);
printMessage.accept("Hello, World!");  // 출력: "Hello, World!"
  • 입력을 받아서 소비하는 함수로, 리턴값이 없습니다.
  • 예시: 문자열을 출력하는 Consumer

Supplier<T>

Supplier<LocalDate> getCurrentDate = () -> LocalDate.now();
LocalDate currentDate = getCurrentDate.get();
System.out.println(currentDate);  // 현재 날짜를 출력
  • 제공하는 함수로, 매개변수가 없고 리턴값만 있는 형태입니다.
  • 예시: 현재 날짜를 제공하는 Supplier

BiFunction<T, U, R>

BiFunction<Integer, Integer, String> multiplyAndConvertToString = (num1, num2) -> String.valueOf(num1 * num2);
String result = multiplyAndConvertToString.apply(5, 3);
System.out.println(result);  // 출력: "15"
  • 두 개의 입력을 받아서 변환한 결과를 반환하는 함수입니다.
  • 예시: 정수 두 개를 곱한 결과를 문자열로 변환하는 BiFunction

UnaryOperator<T>

UnaryOperator<Integer> square = num -> num * num;
int result = square.apply(5);
System.out.println(result);  // 출력: 25
  • 하나의 입력을 받아서 동일한 타입의 결과를 반환하는 함수입니다.
  • 예시: 정수를 제곱하는 UnaryOperator

인터페이스 생성

익명 클래스

public class Main {
    public static void main(String[] args) {
        Function<Integer, Integer> square = new Function<Integer, Integer>() {
            @Override
            public Integer apply(Integer x) {
                return x * x;
            }
        };
        
        int result = square.apply(5);
        
        System.out.println(result);  // 출력: 25
    }
}
  • 익명클래스를 사용해서 인터페이스의 인스턴스를 생성하고 구현을 바로 정의한다.

Lambda 표현식

public class Main {
    public static void main(String[] args) {
        Function<Integer, Integer> square = x -> x * x;
        
        int result = square.apply(5);
        
        System.out.println(result);  // 출력: 25
    }
}
  • 익명 메소드를 사용해서 간결한 인터페이스 인스턴스 생성 방법입니다.
  • 추상 메소드가 하나인, Functional Interface에서 가능합니다.
  • 즉, 추상 메소드가 여러 개 있으면 익명 클래스를 사용해서 인터페이스 인스턴스를 생성해야 합니다.
  • 매개변수의 타입을 생략할 수 있습니다.
  • 단일 실행문인 경우 중괄호 '{}'와 'return'을 생략할 수 있습니다.
  • 매개변수가 단 하나인 경우에는 괄호 '()'를 생략할 수 있습니다.

메소드 레퍼런스

public class Main {
    public static int square(int x) {
        return x * x;
    }
    
    public static void main(String[] args) {
        Function<Integer, Integer> square = Main::square;
        
        int result = square.apply(5);
        
        System.out.println(result);  // 출력: 25
    }
}
  • 람다 표현식에서 입력되는 값을 변경 없이 바로 사용하는 경우 클래스 타입::함수 표현 가능합니다.
  • 입력값을 변경하지 말라는 표현방식이기도 합니다.
  • 생성자 호출 표현은 클래스 타입::new 입니다.
profile
웹 개발에 관심 있습니다.
post-custom-banner

0개의 댓글