Perceive “by” Delegated Properties in Kotlin


Once I first discovered Kotlin, the by operator is an alien to me. What the hell is that? On this article, I will present a easy instance to indicate the the reason why we wish to use this by operator.

Customized Property get() and set()

For instance I wish to create a customized property get() and set() to print out one thing when the property worth is learn and set. I’ll do one thing like this.

class PropertyAccessExample {  
    var worth: String? = null  
        get() {  
            println("property get worth: $discipline")  
            return discipline  
        }  
        set(worth: String?) {  
            println("property set worth from $discipline to $worth")  
            discipline = worth  
        }  

    var anotherValue: String? = null  
        get() {  
            println("property get worth: $discipline")  
            return discipline  
        }  
        set(worth: String?) {  
            println("property set worth from $discipline to $worth")  
            discipline = worth  
        }  
}

enjoyable essential() {
    val example1 = PropertyAccessExample()
    
    example1.worth = "example1"
    
    println(example1.worth)
}

Output:

property set worth from null to example1
property get worth: example1
example1

Please observe that the discipline right here is an implicit discipline. To be taught extra about Properties and Fields in Kotlin, check with this text.

The issue of that is I must implement this practice get() and set() for all of the properties that I wish to monitor. For instance, anotherValue above is the boilerplate code. To cut back the boilerplate code, we use by operator – delegated properties.

“by” Delegated Properties

To implement the by operator, we have to implement the delegated class that has applied getValue() and setValue() operator.

class PropertyDelegate<T>(non-public var worth: T? = null) {  

    operator enjoyable getValue(thisRef: Any?, property: KProperty<*>): T? {  
        println("property get worth: $worth")  
        return worth  
  }  

    operator enjoyable setValue(thisRef: Any?, property: KProperty<*>, worth: T?) {  
        println("property set worth from ${this.worth} to $worth")  
        this.worth = worth  
    }  
}

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

enjoyable essential() {    
    val example2 = PropertyDelegateExample()  
    
    example2.worth = "example2"  
    
    println(example2.worth)  
}

Output:

property set worth from null to example2
property get worth: example2
example2

This line – var worth: String? by PropertyDelegate() mainly means, “the property worth is supplied by PropertyDelegate() delegated class. PropertyDelegate() takes duty to set and get the worth property.

Please additionally observe that the anotherValue boilerplate code is now eliminated!

Frequent Usages of “by” Operator

by lazy

The most typical utilization of delegated property in my view is by lazy. I personally want val over var. So I exploit by lazy rather a lot each time is feasible as a substitute of utilizing lateinit var

non-public val navController: NavController by lazy {
    findNavController()
}

lazy is a delegated property that’s accountable to set the navController. lazy takes in lambda operate and that final line is the return worth of NavController. As soon as navController is accessed, the worth will probably be cached and findNavContorller() will not be referred to as once more within the subsequence accesses.

by viewModels

by viewModelscan be one other quite common utilization of delegated property used to create the ViewModel.

non-public val viewModel by viewModels<MainViewModel> {
    MainViewModelFactory(utility)
}

by viewModels is much like, by lazy which is particular for ViewModel creation. It takes in lambda operate and the final line is the return worth of the implementation of ViewModelProvider.Manufacturing unit interface. For extra detailed usages, you may check with my earlier article right here.

by mutableStateOf

by mutableStateOf is what I discovered just lately whereas engaged on Jetpack Compose venture.

Methodology 1 – MutableState<T> (backing property)

In ViewModel class, as a substitute of utilizing MutableState<T> straight,

non-public val _snackBarStringIdState: MutableState<Int?> =  mutableStateOf(null)  
val snackBarStringId  
  get() = _snackBarStringIdState.worth


_snackBarStringIdState.worth = R.string.no_internet

we are able to use by mutableStateOf

Methodology 2 – by mutableStateOf (non-public set)

var snackBarStringId: Int? by mutableStateOf(null)  
    non-public set


snackBarStringId = R.string.no_internet

Each strategies are comparable. The one distinction is setting the worth, as you may code see within the instance above.

Conclusion

There are different delegated properties reminiscent of observable and storing properties, and you may see the instance right here. Since I seldom use 2 of them, I don’t point out them right here. I’ll replace the “Frequent Usages” part above after I discover them helpful someday.

There are additionally class delegation utilizing by operator to delegate your class implementation to a different object. I additionally hardly ever use this, so I am not running a blog about it right here too.

Related Articles

LEAVE A REPLY

Please enter your comment!
Please enter your name here

Latest Articles