시뻘건 개발 도전기

Method Reference 본문

프로그래밍/JAVA

Method Reference

시뻘건볼때기 2022. 7. 14. 16:01
반응형

Method Reference는 기존에 선언되어있는 method를 지정하고 싶을 때 ::(더블콜론)을 사용해서 사용한다.

Method Reference 아래 4가지의 케이스가 존재한다.

  • 클래스의 static method를 지정
  • 선언된 객체의 instance method를 지정
  • 객체의 instance method를 지정
  • 클래스의 constructor를 지정

 

1. 클래스의 static method를 지정 : {Class Name}::{Static Method Name}

public class Exercise {
    public static void main(String[] args) {
        int num = Integer.parseInt("123");
        System.out.println(num);    // 123

        Function<String, Integer> fucntion = Integer::parseInt;
        System.out.println(fucntion.apply("123"));  // 123

        System.out.println(process("2", "3", Exercise::multiply));  // 6
    }

    public static int process(String x, String y, BiFunction<String, String, Integer> operator) {
        return operator.apply(x, y);
    }

    public static int multiply(String x, String y) {
        return Integer.parseInt(x) * Integer.parseInt(y);
    }
}

2. 선언된 객체의 instance method를 지정 : {Object Name}::{Instance Method Name}

public class Exercise {
    public static void main(String[] args) {
        String string = "hello world";
        System.out.println(string.equals("hello")); // false

        Predicate<String> predicate = string::equals;
        System.out.println(predicate.test("hello"));    // false

        Exercise exercise = new Exercise();
        System.out.println(cal(3, 2, exercise::multiply));  // 6

        exercise.method();  // 8
    }

    public static int cal(int x, int y, BiFunction<Integer, Integer, Integer> operator) {
        return operator.apply(x, y);
    }

    public int multiply(int x, int y) {
        return x * y;
    }

    // 클래스의 instance method안에서 function interface를 이용해서 다른 method를 지정
    public void method() {
        System.out.println(cal(4, 2, this::multiply));
    }
}

3. 객체의 instance method를 지정 : {Class Name}::{Instance Method Name}

public class Exercise {
    public static void main(String[] args) {
        List<User> users = new ArrayList<>();
        users.add(new User(1, "일인자"));
        users.add(new User(2, "이인자"));
        users.add(new User(3, "삼인자"));

        printUserField(users, User::getId); 	// 1 > 2 > 3 > 
        printUserField(users, User::getName);   // 일인자 > 이인자 > 삼인자 > 
    }

    public static void printUserField(List<User> users, Function<User, Object> getter) {
         for(User user : users) {
             System.out.print(getter.apply(user) + " > ");
         }
    }
}

@Getter
@AllArgsConstructor
class User {
    private int id;
    private String name;
}

4. 클래스의 constructor를 지정 : {Class Name}::new

List<User> users = new ArrayList<>();

BiFunction<Integer, String, User> createUser = User::new;
users.add(createUser.apply(1, "일인자"));
users.add(createUser.apply(2, "이인자"));
users.add(createUser.apply(3, "삼인자"));

 

Constructor를 Function으로 지정하는 방법을 활용해서  객체지향의 원리와 함수형 프로그래밍을 함께 결합하여 확장성이 좋은 코드를 생각해낼 수도 있다.

public class Exercise {
    public static void main(String[] args) {
        String[][] inputs = new String[][] {
                {"sedan", "sonata", "Hyundai"},
                {"SUV", "sorento", "kia"}
        };

        /*
         * 만약 inputs로 Car List를 만들어서 리턴하고 싶다고 가정한다면...
         * for문과 if-else if-else문을 통해서 하나하나 세단인지 SUV인지 체크하고 생성자를 사용할 것이다...
         * (만약 수백개의 종류가 있다면 else if가 수백개...)
         */

        Map<String, BiFunction<String, String, Car>> map = new HashMap<>();
        map.put("sedan", Sedan::new);
        map.put("SUV", SUV::new);

        List<Car> cars = new ArrayList<>();

        for(String[] input : inputs) {
            String carType = input[0];
            String name = input[1];
            String brand = input[2];

            cars.add(map.get(carType).apply(name, brand));
        }

        System.out.println(cars);   // [Car(name=sonata, brand=Hyundai), Car(name=sorento, brand=kia)]
    }

}

@AllArgsConstructor
@ToString
abstract class Car {
    protected String name;
    protected String brand;

    public abstract void drive();
}

class Sedan extends  Car {
    public Sedan(String name, String brand) {
        super(name, brand);
    }

    @Override
    public void drive() {
        System.out.println(brand + "의 세단 " + name + "운전.");
    }
}

class SUV extends  Car {
    public SUV(String name, String brand) {
        super(name, brand);
    }

    @Override
    public void drive() {
        System.out.println(brand + "의 SUV " + name + "운전.");
    }
}
반응형

'프로그래밍 > JAVA' 카테고리의 다른 글

Optional  (0) 2022.08.12
Stream  (0) 2022.07.25
Functional Interface  (0) 2022.07.06
Lambda Expression  (0) 2022.07.06
함수형 프로그래밍  (0) 2022.07.06
Comments