data class Person(
    val name: String,
    var isMarried: Boolean,
)

fun main(args: Array<String>) {
    val p1 = Person("john", true)
    p1.isMarried = false

    println(p1)
}

코틀린은 프로퍼티를 언어차원에서 제공합니다.

val인 경우 getter, var인 경우 getter, setter를 만들어줍니다. 사용할 땐 get, set을 붙이지 않고 프로퍼티를 직접 사용 가능합니다.

 

public class JPerson {
    private final String name;
    private Boolean isMarried;

    public JPerson(String name, Boolean isMarried) {
        this.name = name;
        this.isMarried = isMarried;
    }

    public String getName() {
        return name;
    }

    public Boolean isMarried() {
        return isMarried;
    }

    public void setMarried(Boolean married) {
        isMarried = married;
    }
}

똑같은 코드를 자바로 써보면 이렇죠 ㅠ

 

import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.Setter;

@Getter
@Setter
@AllArgsConstructor
public class JPerson {
    private final String name;
    private boolean isMarried;
}

// ...

JPerson p1 = new JPerson("vince", true);
p1.setMarried(true);
System.out.println(p1.isMarried());

자바에서 롬복을 쓴다면 살-짝 편해질 수도 있습니다

참고로 롬복은 boolean 필드에 대해 "is~"로 시작한다면 getter, setter도 is~, set~ 이런식으로 사용이 가능합니다. (https://projectlombok.org/features/GetterSetter)

(Boolean은 안됩니다)

 

// in Java
Person person = new Person("vince", false);
System.out.println(person.getName());    // "vince"
System.out.println(person.isMarried());  // false

코틀린에서도 이와 비슷하게 이름이 is로 시작하는 프로퍼티의 getter는 get이 붙지 않고 원래 이름을 사용하고, setter에는 is를 set으로 바꾼 이름을 사용하게 됩니다.

자바에서 코틀린 클래스를 사용한다면 위처럼 사용 가능합니다.

반대로 자바 클래스가 이처럼 isMarried, setMarried라는 메소드를 제공하면 코틀린에서 isMarried 프로퍼티를 그대로 사용할 수 있습니다.

 

var <propertyName>[: <PropertyType>] [= <property_initializer>]
    [<getter>]
    [<setter>]

프로퍼티의 전체 문법은 위와 같습니다. 읽기 전용인 경우 val로 바꾸고 setter를 없애면 됩니다

 

class Rectangle(val width: Int, val height: Int) {
    val area: Int // property type is optional since it can be inferred from the getter's return type
        get() = this.width * this.height
}

getter가 있으면 타입 추론이 되니까 프로퍼티의 타입은 써도 되고 안써도 됩니다

 

var stringRepresentation: String
    get() = this.toString()
    set(value) {
        setDataFromString(value) // parses the string and assigns values to other properties
    }

setter의 파라미터는 프로퍼티의 타입과 같아야 하기 때문에 타입을 적어줄 필요는 없습니다

 

var counter = 0 // the initializer assigns the backing field directly
    set(value) {
        if (value >= 0)
            field = value
            // counter = value // ERROR StackOverflow: Using actual name 'counter' would make setter recursive
    }

프로퍼티 값을 저장하기 위한 backing field를 사용할 수도 있습니다.

 

private var _table: Map<String, Int>? = null
public val table: Map<String, Int>
    get() {
        if (_table == null) {
            _table = HashMap() // Type parameters are inferred
        }
        return _table ?: throw AssertionError("Set to null by another thread")
    }

backing property 사용 예시입니다.

c#, dart와 비슷한데, 다른 점이라면 코틀린의 backing field는 optional 이라는 점입니다.

 

Reference

반응형