private set


 외부에서 set을 할 수 없도록 하기 위해서 private set을 선언해줄 수 있습니다. 기본 setter의 구현을 변경할 필요가 없으면 body를 정의할 필요없이 접근자를 정의할 수 있습니다.

class ExampleUnitTest {

    @Test

    fun kotlin() {

        var student = Person()

        //student.name = "Park" // 외부에서 set 불가

        student.id = 200

        println("student.id ${student.id} student.name ${student.name}")

        student.printName()


    }


    class Person() {

        var id = 0

            get() =  100

        var name = "Suzuki"

            private set


        fun printName() {

            this.name = "Park" // class 내부에서는 set 가능

            println("this.name ${this.name}")

        }

    }

}

 student.id 100 student.name Suzuki

 this.name Park 



Backing Fields


 이전에 언급했던 getter와 setter을 생략하지 않고 선언하는 방법, 즉 custom 접근자를 작성할 때 backing field를 사용할 수 있습니다. 코틀린 클래스에서는 field를 가질 수 없지만 custom 접근자를 사용할 때 backing field가 필요한 경우가 있습니다. 이때 코틀린은 field라는 식별자를 사용하는 backing field를 제공합니다.

 backing field가 없다면 어떤 문제가 있을까요? 다음의 코드를 보시면 이해가 빠를 것 같습니다.

코틀린

     class Person() {

        var id = 0

            get() =  100

        var name = "Suzuki"

            set(value) { name = value }

    }

 

여기까지 보면 얼핏 생각하기에 name에 value를 할당하여 제대로 set하는 것처럼 보입니다.


Java

       public final void setName(@NotNull String value) {

         Intrinsics.checkParameterIsNotNull(value, "value");

         this.setName(value);

      }


 Java 코드를 보니 재귀함수가 보이고 무한루프에 빠져서 StackOverFlow가 발생할 것으로 보입니다.

아니나 다를까 다음과 같이 친절하게 알려줍니다.



 그럼 field를 사용해봅시다.


코틀린

     class Person() {

        var id = 0

            get() =  100

        var name = "Suzuki"

            set(value) { field = value }

    }


Java

       public final void setName(@NotNull String value) {

         Intrinsics.checkParameterIsNotNull(value, "value");

         this.name = value;

      }


 field 식별자는 오직 property 접근자에서만 사용할 수 있습니다. property를 위한 backing field는 적어도 하나 이상의 기본 접근자를 사용하거나 custom 접근자에서 field 식별자를 사용할 때 만들어집니다.


 따라서 다음과 같은 경우에는 backing field가 없습니다.

val isEmpty: Boolean

    get() = this.size == 0


 참고로 코틀린 1.1 이후부터는 property type을 getter로부터 유추할 수 있다면 생략 가능합니다.

 val isEmpty get() = this.size == 0  // type Boolean을 가짐


+ Recent posts