일급 객체 : 다른 객체들에 일반적으로 적용 가능한 연산을 모두 지원하는 객체
first class : 다른 객체들과 동등하게 다뤄지는 것 의미
자바에서 Integer, String등은 모두 일급 객체
자바에서 함수는 1급 객체에 해당하지 않지만 코틀린, JS 등의 언어에서는 함수가 1급 객체에 해당한다 (변수에 함수를 할당, 사용 가능)
자바의 메소드는 변수에 할당할 수 없고, 함수의 파라미터로 메소드를 넣을 수도 없음.
// 자바스크립트의 경우는 가능!
// 변수에 메소드 할당
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!!");
}
}
일급 컬렉션 특징
// 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.
< 참고 >