Understand "by" Delegated Properties in Kotlin
Tags: kotlin, beginners, android
Published: 2022-12-09 23:00:00

When I first [learned Kotlin](https://vtsen.hashnode.dev/best-way-to-learn-kotlin-for-experienced-programmers), the `by` operator is an alien to me. What the hell is that? In this article, I'm going to provide a simple example to show the reasons why we want to use this `by` operator.

## Custom Property get() and set()

Let's say I want to create a custom property `get()` and `set()` to print out something when the property value is read and set. I will do something like this.

```kotlin
class PropertyAccessExample {  
    var value: String? = null  
        get() {  
            println("property get value: $field")  
            return field  
        }  
        set(value: String?) {  
            println("property set value from $field to $value")  
            field = value  
        }  
  
    var anotherValue: String? = null  
        get() {  
            println("property get value: $field")  
            return field  
        }  
        set(value: String?) {  
            println("property set value from $field to $value")  
            field = value  
        }  
}

fun main() {
    val example1 = PropertyAccessExample()
    // property set
    example1.value = "example1"
    // property get
    println(example1.value)
}
```

Output:

```plaintext
property set value from null to example1
property get value: example1
example1
```

Please note that the `field` here is an **implicit field**. To learn more about Properties and Fields in Kotlin, refer to this article.

- [Understand Fields and Properties in Kotlin](https://vtsen.hashnode.dev/understand-fields-and-properties-in-kotlin)

The problem of this is I need to implement this custom `get()` and `set()` for all the properties that I would like to monitor. For example, `anotherValue` above is the boilerplate code. To reduce the boilerplate code, we use `by` operator - delegated properties.

## "by" Delegated Properties

To implement the `by` operator, we need to implement the delegated class that has implemented `getValue()` and `setValue()` operator.

```kotlin
class PropertyDelegate<T>(private var value: T? = null) {  
  
    operator fun getValue(thisRef: Any?, property: KProperty<*>): T? {  
        println("property get value: $value")  
        return value  
  }  
  
    operator fun setValue(thisRef: Any?, property: KProperty<*>, value: T?) {  
        println("property set value from ${this.value} to $value")  
        this.value = value  
    }  
}

class PropertyDelegateExample {  
    var value: String? by PropertyDelegate()  
    var anotherValue: String? by PropertyDelegate()  
}

fun main() {    
    val example2 = PropertyDelegateExample()  
    // property set  
    example2.value = "example2"  
    // property get  
    println(example2.value)  
}
```

Output:

```plaintext
property set value from null to example2
property get value: example2
example2
```

This line - `var value: String? by PropertyDelegate()` basically means, "the property value is **provided by** `PropertyDelegate()` delegated class. `PropertyDelegate()` takes responsibility to set and get the `value` property.

Please also note that the `anotherValue` boilerplate code is now removed!

## Common Usages of "by" Operator

### by lazy

The most common usage of delegated property in my opinion is [by lazy](https://vtsen.hashnode.dev/complete-c-to-kotlin-syntax-comparisons#heading-by-lazy-delegated-properties). I personally prefer `val` over `var`. So I use `by lazy` a lot whenever is possible instead of using `lateinit var`

```kotlin
private val navController: NavController by lazy {
	findNavController()
}
```

`lazy` is a delegated property that is responsible to set the `navController`. `lazy` takes in [lambda function](https://vtsen.hashnode.dev/complete-c-to-kotlin-syntax-comparisons#heading-lambda-methods-functions) and that last line is the return value of `NavController`. Once `navController` is accessed, the value will be cached and `findNavContorller()` won't be called again in the subsequence accesses.

### by viewModels

`by viewModels`is also another very common usage of delegated property used to create the `ViewModel`.

```kotlin
private val viewModel by viewModels<MainViewModel> {
	MainViewModelFactory(application)
}
```

`by viewModels` is similar to, `by lazy` which is specific for `ViewModel` creation. It takes in lambda function and the last line is the return value of the implementation of `ViewModelProvider.Factory` interface. For more detailed usages, you can refer to my previous article [here](https://vtsen.hashnode.dev/recommended-ways-to-create-viewmodel-or-androidviewmodel#heading-by-viewmodels-activityviewmodels).

### by mutableStateOf

`by mutableStateOf` is what I learned recently while working on Jetpack Compose project.

**Method 1 -** `MutableState<T>` (backing property)

In `ViewModel` class, instead of using `MutableState<T>` directly,

```kotlin
private val _snackBarStringIdState: MutableState<Int?> =  mutableStateOf(null)  
val snackBarStringId  
  get() = _snackBarStringIdState.value

// setting the value in ViewModel class
_snackBarStringIdState.value = R.string.no_internet
```

we can use `by mutableStateOf`

**Method 2 -** `by mutableStateOf` (private set)

```kotlin
var snackBarStringId: Int? by mutableStateOf(null)  
    private set

// setting the value in ViewModel class 
snackBarStringId = R.string.no_internet
```

> Both methods are similar. The only difference is setting the value, as you can code see in the example above.

## Conclusion

There are other delegated properties such as observable and storing properties, and you can see the example [here](https://kotlinlang.org/docs/delegated-properties.html). Since I seldom use 2 of them, I do not mention them here. I will update the "Common Usages" section above when I find them useful one day.

There are also [class delegation](https://kotlinlang.org/docs/delegation.html#overriding-a-member-of-an-interface-implemented-by-delegation) using `by` operator to delegate your class implementation to another object. 

To see more info about it, read the following article:
- [What is Delegation Interface in Kotlin?](https://vtsen.hashnode.dev/what-is-delegation-interface-in-kotlin)

---

*Originally published at [https://vtsen.hashnode.dev](https://vtsen.hashnode.dev/understand-by-delegated-properties-in-kotlin)*.