Home NhnAcademy 선발교육과정 17일차 (lambda)
Post
Cancel

NhnAcademy 선발교육과정 17일차 (lambda)

방문자 (visitor pattern)

  • Visitor pattern 은 데이터와 구조를 분리합니다.
  • 데이터 구조 안을 돌아다니는 주체인 방문자를 나타내는 클래스를 준비해서 처리에 맡긴다.
  • 새로운 처리를 추가하고 싶을 때 새로운 방문자를 만들고 데이터 구조는 방문자를 받아들이면 된다.
  • OCP(개방-폐쇠)원칙을 적용하는 방법중 하나
    • 확장에는 열려있음
      • 클래스를 설계할 때, 특별한 이유가 없는 한 확장을 금지 해서는 안됨
    • 수정에는 닫혀있음
      • 즉 확장을 할 때 기존 클래스를 수정하면 안됨.
    • 실제 로직을 가지고 있는 객체 (Visitor)가 로직을 적용할 객체(Element)를 방문하면서 실행하는 패턴.
      • 아래 예제에서 Element는 item 입니다.

디스패치란?

  • 어떤 메소드를 호출할 것인가를 결정하고 결정된 메소드를 실행하는 과정(행위)

정적 디스패치

  • 컴파일 시점에 특정 메소드를 호출할 것이라고 미리 명확하게 알고 있는 것
  • 메소드 오버로딩
  • 메소드 시그니쳐
  • 동작 방식
    • 컴파일 전 단계에서 인자의 타입을 알수있기 때문에 오버라이드로 구현만 하면된다.

동적 디스패치

  • 정적 디스패치와 반대로 컴파일러가 어떤 메서드를 호출하는지 알수 없습니다.
  • 동적 디스패치는 호출할 메서드를 런타임 시점에서 결정한다
  • 동작 방식
    • 객체 내에 this를 던져줄수 있는 메서드를 만들어 인자로 visitor를 받는다.
    • visitor에서 this를 받아 그에 오버라이드 된 메서드를 선택하여 처리한다.

lambda

  • interface 구현
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
enum Operator{
  ADD,SUB
}
interface Calcurator{
  int calc(int a, int b, Operator operator);
}
public class Example02 {
  public static void main(String[] args) {
    int a = 100;
    int b =10;
    Calcurator calcurator = (int x, int y, Operator operator) -> {
      switch (operator){
        case ADD:
          return x+y;
        case SUB:
          return x-y;
        default:
          return 0;
      }
    };
    System.out.println("더하기:" + calcurator.calc(a,b,Operator.ADD));
    System.out.println("빼기:" +  calcurator.calc(a,b,Operator.SUB));
  }
}

위와 같이 인터페이스를 생성하고 lambda로 구현하는 방법도 있다.

  • Supplier< T >
    • 파라미터 없이 반환 값만 갖는 함수형 인터페이스이다.
      1
      2
      3
      4
      5
      6
      7
      
      public class Supplier {
      public static void main(String[] args) {
      //TODO Supplier
      Supplier<User> supplier = () -> new User("Sangwoong",25);
      System.out.println(supplier.get());
      }
      }
      

위와 같이 똑같은 객체를 반복 생성 해야할 때 사용할 수 있다.

  • Consumer< T >
    • T를 입력 받아서 처리하는 함수 변환 값은 없다.
1
2
3
4
5
6
7
8
9
10
public class Consumer {
  public static void main(String[] args) {
    User user = new User("홍길동", 25);
    //TODO Consumer
    Consumer<User> consumer1 = (User inputUser) -> inputUser.toString();
    consumer1.accept(user);
    Consumer<User> consumer2 = User::toString;
    consumer2.accept(user);
  }
}

위와 같이 User 를 받아 toString을 호출하는 Consumer 를 구현한다고 하면 Consumer2 처럼 :: 을 통해 간단하게 작성할 수 있다.

  • Function<T,R>
    • T를 입력받아 R를 리턴하는 함수
1
2
3
4
5
6
7
8
9
10
11
12
public class Function {
  public static void main(String[] args) {
    User user = new User("홍길동", 25);
    //TODO Function
    List<User> users = new ArrayList<>();
    Function<List,Integer> function1 = (List lists) -> lists.size();
    System.out.println(function1.apply(users));
    users.add(user);
    Function<List, Integer> function2 = List::size;
    System.out.println(function2.apply(users));
  }
}

위와 같이 User 를 받아 size() 호출하는 Function 를 구현한다고 하면 Function2 처럼 :: 을 통해 간단하게 작성할 수 있다.

  • Predicate
    • T를 매개 변수로 받아 boolean 을 리턴한다.
1
2
3
4
5
6
7
8
public class Predicate {
  public static void main(String[] args) {
    User user = new User("홍길동", 25);
    //TODO Predicate
    Predicate<User> predicate = (User predicateUser) -> predicateUser.getAge() > 25;
    System.out.println(predicate.test(user));
  }
}

위와 같이 User를 받아서 나이가 25보다 높으면 true 아니면 false 를 출력하게 작성할 수 있다.

Effectively final 이란?

  • final이 붙지 않은 변수의 값이 사실상 변경되지 않는다면. 그 변수는 Effectively final ( 사실상 final ) 이라고 합니다.
  • java8에서 도입 되었으며 익명 클래스 또는 람다식이 사용된 코드에서 쉽게 찾아 볼 수 있습니다.
This post is licensed under CC BY 4.0 by the author.