phantasmicmeans 기술 블로그

8. Kotlin - Backing Field 본문

Programming/Kotlin

8. Kotlin - Backing Field

phantasmicmeans 2021. 1. 22. 12:55

field Keyword

name 프로퍼티의 재 정의된 setter를 살펴보면 field 라는 키워드를 볼 수 있다. field에 값을 넣는 것을 보니 무언가 name의 대리자 느낌이 든다.

class Test {
    var name: String = "" 
        set(value) { 
            field = if (value.isNotEmpty()) value else "" 
        }
}

Backing Fields

코틀린은 Backing Field가 필요하면 알아서 제공한다. 또한 Backing field는 접근자 내에서 field 키워드로 참조할 수 있다. 바로 위 예제에서 setter 내에 field 라고 선언되어진 부분을 볼 수 있는데, 이 field가 Backing Field를 참조하고 있는 상태인 것이다.

 

그럼 코틀린에서 말하는 Backing field가 무엇일까? 간단히 말하면 java field 이다.

 

코틀린 컴파일러는 접근자들을 default로 generate 시키는데, 실제로 이를 디컴파일해보면 프로퍼티의 value를 담기 위해 java의 field를 사용한다.

 

아래 코틀린 클래스를 보자

class Test {
    var size = 0;
    var isEmpty = false
}

size, isEmpty 프로퍼티를 가진 Test 클래스를 디컴파일하면 아래와 같은 java 클래스를 추출할 수 있다. default getter, setter 가 generate 되었고 size, isEmpty 필드를 포함한다.

public final class Test {
   private int size;
   private boolean isEmpty;

   public final int getSize() {
      return this.size;
   }

   public final void setSize(int var1) {
      this.size = var1;
   }

   public final boolean isEmpty() {
      return this.isEmpty;
   }

   public final void setEmpty(boolean var1) {
      this.isEmpty = var1;
   }
}

size, isEmpty 필드를 코틀린에서 Backing Field 라 부른다.

 

default getter, setter를 사용한 경우 모든 필드가 Backing Field로 생성된다.


이와 반대로 getter, setter를 customize 해보자.

class Test {
    var size = 0;
    var isEmpty
        get() = size == 0
        set(value) {
            size = size * 2
        }
}

isEmpty 프로퍼티의 getter, setter를 재정의 하였다. 눈 여겨 볼 점은 getter, setter 가 size의 결과에 따라 변경된다는 점이다.

public final class Test {
   private int size;

   public final int getSize() {
      return this.size;
   }

   public final void setSize(int var1) {
      this.size = var1;
   }

   public final boolean isEmpty() {
      return this.size == 0;
   }

   public final void setEmpty(boolean value) {
      this.size *= 2;
   }
}

디컴파일 해보면 이전과는 달리 isEmpty 필드가 사라진 것을 알 수 있다. isEmpty(), setEmpty(boolean value) 모두 size에 의해 결정되기 때문에 isEmpty 필드가 필요 없다고 판단되었기 때문이다.

 

이 경우는 Backing Field가 size 하나뿐이게 된다.

 

Why Backing Fields?

왜 Backing Field가 필요할까?field 키워드는 Backing Field를 참조한다고 했다.
field 키워드가 없다면 난해한 일이 일어날 수 있는데 이유는 아래를 보자..

 

코틀린에서 접근자를 통해 프로퍼티에 접근하는 경우 foo.bar와 같은 dot notation을 사용한다. 접근자를 통해 프로퍼티의 값을 세팅하는 경우도 마찬가지이다.

foo.bar = "a" 

위와 같은 코드는 필드에 값을 put 하는 것이 아니고, 실제로는 setter call을 실행하게 된다.

아래 코드를 보자.

 

field 키워드 대신 this.size = value 를 사용하였다. 이는 setter call을 사용하게 되고, 디컴파일해보면 recursive 하게 setter call 이 이루어진다는 것을 알 수 있을 것이다.

class Test {
    var size: Int = 0
    set(value) {
        if (value >= 0) this.size = value
    }
}

실제로 디컴파일하면 아래와 같은 setter를 볼 수 있고, 무한 재귀에 빠질 수 있는 문제점을 가지고 있다.

class Test {
    private int size = 0;
    public void setSize(int value) {
        if (value >= 0) setSize(value);
    }
    public int getSize() {
        return setSize;
    }
}

이러한 이유에 의해 field 키워드를 사용해 Backing Field에 접근하여 값을 변경하는 것이다.

'Programming > Kotlin' 카테고리의 다른 글

10. Kotlin - Functional Interface  (0) 2021.01.22
9. Kotlin - Interface  (0) 2021.01.22
7. Kotlin - Properties  (0) 2021.01.22
6. Kotlin - Class Inheritance  (0) 2021.01.22
5. Kotlin - Class  (0) 2021.01.22
Comments