3장 - 자바 클래스에서 코틀린 클래스로

3장 - 자바 클래스에서 코틀린 클래스로를 정리한 내용입니다.

간단한 값 타입

  • EmailAddress 클래스는 값 타입(value type)이다.

package travelator;

import java.util.Objects;

public class EmailAddress {
    private final String localPart; // <1>
    private final String domain;

    public static EmailAddress parse(String value) { // <2>
        var atIndex = value.lastIndexOf('@');
        if (atIndex < 1 || atIndex == value.length() - 1)
            throw new IllegalArgumentException(
                "EmailAddress must be two parts separated by @"
            );
        return new EmailAddress(
            value.substring(0, atIndex),
            value.substring(atIndex + 1)
        );
    }

    public EmailAddress(String localPart, String domain) { // <3>
        this.localPart = localPart;
        this.domain = domain;
    }

    public String getLocalPart() { // <4>
        return localPart;
    }

    public String getDomain() { // <4>
        return domain;
    }

    @Override
    public boolean equals(Object o) { // <5>
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        EmailAddress that = (EmailAddress) o;
        return localPart.equals(that.localPart) &&
            domain.equals(that.domain);
    }

    @Override
    public int hashCode() { // <5>
        return Objects.hash(localPart, domain);
    }

    @Override
    public String toString() { // <6>
        return localPart + "@" + domain;
    }
}
  • 인텔리J에 'Convert Java File to Kotlin File' 기능으로 EmailAddress.kt로 만들수 있다.

  • 주 생성자 안에 val을 붙여 프로퍼티를 선언하는 형태로 클래스를 정의할 수 있다. (옆 탭은 동일한 자바 코드)

  • 파라미터를 한 줄에 하나씩 배치해 가독성을 높일 수 있다.

  • 코틀린의 생성자에 val로 선언된 프로퍼티는 getDomain() 게터를 제공해준다.

  • 자바의 EmailAddress 코드는 전형적인 값 타입 클래스로 보일러플레이트 코드가 많다.

  • 코틀린은 data 변경자를 붙여 값 타입의 데이터 클래스를 지원한다.

데이터 클래스의 한계

  • equals, hashCode, toString 함수를 생성해준다.

  • 프로퍼티 일부를 다른 값을 대치할 수 있는 copy 함수도 제공한다.

  • 돈이라는 개념을 추상화 해놓은 타입인 Money 클래스를 살펴보자.

circle-info

함수 이름의 set, with 접두사

BigDecimal.setScale는 객체의 상태를 변경하지 않고 setScale를 적용한 새로운 BigDecimal을 반한다. 이때는 set 접두사를 피하고 with 접두사를 사용하는 편이 좋다.

amount.withScale(currency.getDefaultFractionDigits())

코틀린은 이부분을 확장함수로 풀 수 있다.

fun BigDecimal.withScale(int scale, RoundingMode mode) = setScale(scale, mode)

  • Money 클래스를 코틀린으로 변환하면 다음과 같다.

  • Moeny 클래스는 생성자가 private으로 감추어져 있다.

  • 정적 팩토리 생성 함수로만 Money 객체를 만들수 있도록 되어 있다.

  • 클래스 생성시 내부 구현에 감춰야하는 세부 사항이 있다는 뜻이다.

  • 데이터 클래스는 copy 함수를 통해 내부 구현에 적합하지 않은 객체를 생성할 수 있는 허점이 있다.

circle-info

프로퍼티 사이에 불변 조건을 유지해야 하는 값 타입은 데이터 클래스를 사용해서 정의하면 안된다.

다음으로 나아가기

  • 데이터 클래스를 사용해 값 타입 구현시 보일러플레이트 코드들을 많이 줄일 수 있다.

  • 값 객체 프로퍼티들이 서로 불변조건을 유지해야 하거나 내부를 캡슐화해야 한다면 데이터 클래스는 적합하지 않다.

Last updated