Kotlin: 何时使用自定义访问器getter

Kotlin: 何时使用自定义访问器getter,第1张

Kotlin: 何时使用自定义访问器getter

记一个有意思的问题,在国外发现了一个帖子,为了避免有时候看不到,这里将原文复制如下:

Kotlin Demystified: When to use custom accessors

While working on UAMP, I found it convenient to wrap several support library classes in a helper for a variety of reasons. One of the features I wanted from this wrapper was the ability to quickly reference the “transport controls” class, which is used to give commands such as play and pause.
To make it convenient, I added a property to my wrapper:

val transportControls: MediaControllerCompat.TransportControls
    = mediaController.transportControls

The thing to keep in mind is that mediaController is a lateinit var, because it’s created during a callback to a service connection. Thus this code crashes immediately when the app is run:

E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.example.android.uamp.next, PID: 18641
    java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.android.uamp.next/com.example.android.uamp.MainActivity}:
    kotlin.UninitializedPropertyAccessException: lateinit property mediaController has not been initialized

The fix is to add a custom accessor to this property:

val transportControls: MediaControllerCompat.TransportControls
    get() = mediaController.transportControls

But why?
The easiest way to understand what’s going on is to look at the bytecode for the two variations. Doing this in Android Studio is as easy as Tools > Kotlin > Show Kotlin Bytecode. Then select the Decompile button to look at the equivalent Java code.
Without get():

@NotNull
private final TransportControls transportControls = mediaController.getTransportControls();
@NotNull
public final TransportControls getTransportControls() {
    return this.transportControls;
}

With get():

@NotNull
public final TransportControls getTransportControls() {
    return mediaController.getTransportControls();
}

In the first case, a member variable transportControls was being set when the class was constructed. In the second, it actually calls mediaController.getTransportControls() every time the transportControls property is accessed.
In my case, this is exactly what I wanted to do. I don’t want to save the object returned from mediaController.getTransportControls() in my object, I just want to make it more convenient to write that code. Because of this, the code should be val transportControls get() = ....
This isn’t always the right approach, however. Take this code for example:

val ticket get() = findTicketInDb()

Yikes! Each time ticket is accessed, the code will search the database for the ticket! That’s probably not what we want. In this case the right approach would be to write:

val ticket = findTicketInDb()

This will call findTicketInDb() once, when the object is created, and return that same value each time the property ticket is accessed.
Kotlin properties can be deceptively simple. Understanding the difference between properties computed once when the object is created, and those with custom get() methods, which are computed each time the property is accessed, can mean the difference between writing clear code and introducing unintended behavior into your app.
Be sure to follow the Android Developers publication for more great content, and stay tuned for more articles on Kotlin!

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/zaji/5685592.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-17
下一篇 2022-12-17

发表评论

登录后才能评论

评论列表(0条)

保存