본문 바로가기
자바

익명 클래스, 함수형 인터페이스 그리고 람다

by 참새는 짹짹 2021. 3. 14.

자바는 객체를 1급 시민으로 갖는다

1급 시민이란

  • 변수에 담을 수 있다
  • 인자로 전달할 수 있다
  • 반환값으로 전달할 수 있다

다음과 같은 조건을 충족하는 것을 말하고

자바는 객체 지향 프로그래밍에 맞게

객체를 1급 시민으로 갖고 있다

하지만

함수형 프로그래밍이 대두되면서

함수를 객체로 담을 수 없는 자바는

💡
이를 가능하게 하고자 함수형 인터페이스를 가지고 람다식을 도입하여 함수도 1급 시민처럼 사용할 수 있게 했다

익명 클래스


앞서 말한 함수를 1급 시민처럼

사용할 수 있게 된 배경을 알기 위해선

익명 클래스로 거슬러 올라간다

예전 알고리즘 문제를 풀 때

어떤 객체를 만들고 그 객체의 한 요소를 기준으로

정렬을 하고 싶을 때

아래와 같이 구현을 했었다

Collections.sort(list, new Comparator<Student>() {
	@Override
	public int compare(Student s1, Student s2) {
		return s1.getScore() - s2.getScore();
	}
});

위에서 사용한 Collections.sort 함수는

sort(List<T> list, Comparator<? super T> c)

위와 같은 형태를 가지며

두 번째 인자로 Comparator 인터페이스를 받는다

( 즉, Comparator 인터페이스를 구현한 객체를 받는다 )

Comparator 인터페이스를 구현한 클래스를 따로 정의할 수도 있지만

위처럼 인자가 들어가는 자리에

new 연산자 인터페이스 를 통해

인터페이스를 구현한 이름 없는 클래스

인 익명클래스를 만들어 그 객체를 넘길 수도 있다

일회성으로 쓸 클래스 같은 경우

이처럼 익명클래스가 자주 사용된다

💡
만들어진 클래스가 아니기 때문에 기존에 있는 클래스나 인터페이스 명을 가지고 이를 상속 받거나 구현한 클래스를 만든다

함수형 인터페이스


위의 Comparator 인터페이스는

compare 함수 하나만을 추상 메서드로 갖는다

( 정확히는 equals 도 갖지만 equals은 Object의 public 함수이기에 이는 제외하고 카운트 한다 )

추상 메서드
  • 구현하는 클래스가 재정의하여 그 기능을 채워 사용할 것을 강제

이처럼

하나의 추상 메서드를 갖는

인터페이스를 함수형 인터페이스라 하고

이런 함수형 인터페이스는 람다식으로 변환이 가능하다

람다식


Collections.sort(list, (s1, s2) -> s1.getScore() - s2.getScore());

위에서 Comparator 인터페이스로 익명클래스를 사용하여

정렬을 구현했지만

람다식을 사용하여 위처럼 간결하게 표현할 수가 있다

이런 람다식은

자바 8부터 지원하기 시작했으며

함수형 인터페이스에 한해서 변환이 가능하다

그 이유는
(s1, s2) -> s1.getScore() - s2.getScore()

위와 같은 람다식을 예로 들면

(s1, s2)인자로 받고

s1.getScore() - s2.getScore()리턴 한다는 뜻인데

이는

int compare(T o1, T o2);

Comparator 인터페이스의 compare 추상 메서드와 맵핑된 람다식이다

만일, Comparator 인터페이스에 추상 메서드가 또 있다면

💡
어떤 추상 메서드를 맵핑해야 하는지 정보가 더 필요할 수 밖에 없다

람다식 작성


이처럼 원래

  • 함수형 인터페이스를 구현한 익명클래스가 들어가던 자리에
  • 추상 메서드를 구현한 람다식

이 들어갈 수가 있게 된다

때문에

람다식의 형태도 구현한

추상 메서드의 형태와 일치해야 하는데

compare 추상 메서드를 예로 들면

int compare(T o1, T o2);

  • 제너릭 타입을 갖는
  • 2개인자를 받고
  • int 타입리턴한다

따라서, 람다식도

(s1, s2) -> s1.getScore() - s2.getScore()

(s1, s2)
  • 같은 타입의 객체
  • 2개인자
→ s1.getScore() - s2.getScore()
  • int 타입을 가지는 식을 리턴값으로 가져야 한다

📌
람다식이여도 중괄호 {} 를 사용하여 여러 줄로 구현할 수 있으며 return 으로 리턴값을 명시한다

람다식 사용


이렇기 때문에

자바에서는

여러 타입의 인자와 리턴 타입을 가지는

다양한 함수형 인터페이스를 지원해주고 있다

여기서

알맞은 함수형 인터페이스를 인자로 받아

추상메소드를 사용하면

람다식을 받아 쓰도록 구현할 수가 있다

'자바' 카테고리의 다른 글

객체 지향과 다형성 그리고 SOLID  (0) 2021.01.05

댓글