본문 바로가기

코틀린 Kotlin

Kotlin (7) getter 와 Assignment (=)의 차이

Kotlin 예제들을 보다보면 get() 통해서 해당 프로퍼티에 직접적으로 값을 대입하지 않고(=) get()을 통해 다른 객체의 값을 사용하는 경우가 있습니다. 

 

예를들어, 안드로이드 스튜디오에서 제공하는 Jetpack 의 ViewModel에서 LiveData를 사용할 때 MutableLiveData와 함께 사용해서 LiveData에 MutableLive의 value를 get() 하는 상황들을 많이 보셧을겁니다.

 

 

어떤 경우에 직접 대입 Assignment (=) 을 사용하지 않고 get()를 사용하는지 살펴보도록 하겠습니다.

 

1.val, var

코틀린의 프로퍼티는 기본적으로 field와 getter / setter를 자동생성 해줍니다.

예를들어 변수를 하나만들어서 이 변수를 자바 코드로 변환을 한다면

아래와 같이 자동 생성이 된다는걸 볼 수 있습니다.

 

- Val

 // kotlin
class GetterTest {
    val nullableVer: Int? = null
    val nonNullVer = 0
}
 // java
public final class GetterTest {
   @Nullable
   private final Integer nullableVer;
   private final int nonNullVer;

   @Nullable
   public final Integer getNullableVer() {
      return this.nullableVer;
   }

   public final int getNonNullVer() {
      return this.nonNullVer;
   }
}

변수를 val로 사용할 경우 setter는 만들어지지 않고 getter만 만들어집니다.

 

-Var

// kotlin
class GetterTest {
    var nullableVer: Int? = null
    var nonNullVer = 0
}
// java
public final class GetterTest {
   @Nullable
   private Integer nullableVer;
   private int nonNullVer;

   @Nullable
   public final Integer getNullableVer() {
      return this.nullableVer;
   }

   public final void setNullableVer(@Nullable Integer var1) {
      this.nullableVer = var1;
   }

   public final int getNonNullVer() {
      return this.nonNullVer;
   }

   public final void setNonNullVer(int var1) {
      this.nonNullVer = var1;
   }
}

var 로 변수를 생성할 경우 getter setter 두개다 동시에 생성이 되는것을 볼 수 있습니다.

 

2. get(), set()

하지만 만약 getter / setter를 명시적으로 커스텀을 해야할때 get(), set()를 사용합니다. 

//kotlin 
class GetterTest {
    var getterVar: Int = 0
        get() = field
        set(value) {
            field = value * 2 
        }
    
    init {
        getterVar = 2
        println(getterVar) //output:4
    }
}
//java
public final class GetterTest {
   private int getterVar;

   public final int getGetterVar() {
      return this.getterVar;
   }

   public final void setGetterVar(int value) {
      this.getterVar = value * 2;
   }

   public GetterTest() {
      this.setGetterVar(2);
      int var1 = this.getGetterVar();
      boolean var2 = false;
      System.out.println(var1); //output:4
   }
}

위 예제는 set 할때 대입되는 값이 *2로 field에 할당하도록 커스텀 한것 입니다.

그래서 자바로 변환한 코드를 보면 setGetterVar 함수에서 매개변수로 받는 value 를 *2를 하여 field에 값을 대입 하는것을 볼 수 있습니다.

output : 4 

 

3. get() 과 Assignment (=)

서로 비슷해보이는 get()과 =를 한번 보도록 하겠습니다.

//kotlin
class GetterTest {
    val normalVar = 5

    val getterVar: Int
        get() = 5
}

= 으로 값을 대입하는 normalVer 변수와 

get() 을 사용해서 값을 return 받는 getterVar가 있습니다. 

이 코드 또한 자바 코드로 변환해보면 아래와 같이 됩니다.

//java 
public final class GetterTest {
   private final int normalVar = 5;

   public final int getGetterVar() {
      return 5;
   }

   public final int getNormalVar() {
      return this.normalVer;
   }
}

normalVar 의 경우 field 값이 5로 할당이 됩니다.

getterVar의 경우 field가 따로 생성되지 않고 getter 함수만 생성이되었습니다. 

4. get() 과 Assignment (=)의 차이 

getter로 return만 받는 객체의 경우 사실 필드는 생략되었으며,

getter 함수만 생성되서 값을 return 하고 있다는 사실을 볼 수 있었습니다. 

 

아래 예제를 보겠습니다. 

//kotlin 
class GetterTest {
    var number = 5
    private val getterVar
        get() = number

    private val normalVar = number
    init {
        number+= 10
        println(getterVar) // output: 15
        println(normalVer) // output: 5
    }
}

getterVar는 getter를 통해 number 객체를 return하고 

normalVar는 직접 number의 값을 복사해서 대입 합니다. 

 

그래서 number 의 값이 바뀐다면,

getterVar는 number의 객체 자체를 return 하기 때문에 

number의 값을 return합니다.

 

반대로 normalVar는 number의 값이 바뀌어도 영향을 받지 않습니다. 

 

즉, 변수에 getter만 사용하는것은 field를 생성하지 않고

getter() 함수를 통해 특정 객체만 return 하겠다는 의미이고

 

변수에 = 로 값을 대입하는 것은 field 를 생성하는 동시에 field의 값을 할당하는 것입니다.

=로 값을 대입한 변수의 getter는 field의 값을 return 해줍니다.

 

이상 getter 와 Assignment의 차이를 알아봤습니다.