일급 컬렉션 First Class Collection

Haechan Kim·2024년 2월 1일
0

Modern Java

목록 보기
5/5

First Class Object (일급 객체)

일급 객체 : 다른 객체들에 일반적으로 적용 가능한 연산을 모두 지원하는 객체

first class : 다른 객체들과 동등하게 다뤄지는 것 의미

자바에서 Integer, String등은 모두 일급 객체
자바에서 함수는 1급 객체에 해당하지 않지만 코틀린, JS 등의 언어에서는 함수가 1급 객체에 해당한다 (변수에 함수를 할당, 사용 가능)

1급 객체의 조건

  • 변수에 할당(assignment) 가능
  • 함수의 인자(argument)로 전달할 수 있어야 함
  • 다른 함수의 결과로서 리턴될 수 있음

JAVA

자바의 메소드는 변수에 할당할 수 없고, 함수의 파라미터로 메소드를 넣을 수도 없음.

// 자바스크립트의 경우는 가능!
// 변수에 메소드 할당
const hello = function() {
  console.log("hello");
}

// 파라미터로 메소드 전달
public static void print(Object func) {
	func();
}

but, 람다식 or 익명 클래스를 활용해서 변수나 매개변수에 할달 할 수 있고, 리턴 값으로도 사용할 수 있기 때문에 일급 객체의 조건 충족한다.

import java.util.function.Consumer;

// 메소드를 변수에 담는 경우 (람다 사용)
public class Main
{
	public static void main(String[] args) {
		Consumer<String> consumer = (string) -> System.out.println(string);
		consumer.accept("hello!");
	}
}
// 함수의 파라미터로 전달하는 경우
public class Main
{
    public static void print(Consumer<String> consumer, String str) {
        consumer.accept(str);
    }
    
	public static void main(String[] args) {
		print((str) -> System.out.println(str), "hello!");
	}
}
// 함수의 리턴값으로 사용
public class Main
{
    public static Consumer<String> hello() {
        // 람다 함수 자체를 리턴
        return (str) -> {
            System.out.println(str);
        };
    }
    
	public static void main(String[] args) {
		Consumer<String> consumer = hello();
		consumer.accept("hello!!");
	}
}

First Class Collection (일급 컬렉션)

  • 컬렉션 포함한 클래스는 반드시 다른 멤버 변수가 없어야 함.
  • 컬렉션을 wrapping한 변수 있다면, 다른 멤버 변수는 없어야 함.

일급 컬렉션 특징

  • 컬렉션 객체는 변수나 매개변수에 할당할 수 있다
  • 컬렉션 객체는 다른 객체와 동등한 지위를 가진다
  • 반환값으로 사용될 수 있다
  • 필요한 경우 메서드 생성 가능
// 1. Car 클래스
// 일급 컬렉션 사용하지 않은 코드
public class Car {

    private final String name;
    private int position;

    // 처음에 자동차 생성 위치
    public Car(final String name) {
        this.name = name;
        position = 0;
    }

    // 한칸 이동
    public void move() {
        this.position++;
    }
    
    public String getName() {
        return name;
    }

    public int getPosition() {
        return position;
    }
}
// 2. Cars 클래스 (일급 클래스 사용)
public class Cars {

    // 일급 컬렉션에는 멤버 변수 하나만 있어야 함!
    private final List<Car> cars;

    public Cars(final String<Car> name) {
        this.cars = cars;
    }

    // Cars가 관리하는 모든 차 한칸 이동
    public void move() {
        for (final Car car ; cars) {
            car.move();
        }
    }
}

장점

Cars를 통해 List< Car >를 관리했을 때 장점?

  • 도메인의 상태, 행위를 한곳에서 관리 가능.
// 컨트롤러에서 차 움직이 때
// 1. 일급 객체 사용할 때
cars.moveAll();

// 2. 사용하지 않을 때
List<Car> cars = maekCars();
for (Car car : cars) {
	car.move();
}

1의 경우 Cars의 moveAll() 통해서 Cars가 관리하는 모든 Car 도메인 제어할 수 있음 -> Car 도메인은 자신 행위에만 충실할 수 있음

  • 비지니스 로직에 종속적이지 않다 (모든 행위는 도메인이 알고 있기 때문)
    도메인이 자기 행위에만 집중 가능.

  • 콜렉션의 불변 보장

public void startGame() {
    // 1. 일급 컬렉션 사용 했을 때, 
    // setter, add등 직접 만들지 않는 한한 불변 보장!
    Cars cars = new Cars(makeCars());
    // add는 없는 메소드
    Cars.add(new Car("car1"));
    
    // 2. 일급 컬렉션 사용하지 않을 때,
    // List의 add, remove등의 메소드로 불변 보장 X
    final List<Car> cars = makeCars();
    // List.add
    cars.add(new Car("car2"));
}

1의 경우 car1 추가 불가능. add 메소드를 만들지 않았기 때문.
but 2의 경우 final로 선언 했기 때문에 재할당은 불가능하지만,
컬렉션 메서드 (List의 add, remove등) 사용해 내부 변경 가능.

즉 Car 클래스가 컬렉션 타입(여기서는 List)에 의존성을 갖게 됨. bad.

< 참고 >

0개의 댓글