当我们在 Kotlin 中使用 get() 时有什么区别

oye*_*hib 8 java variables get kotlin

我想了解这两种说法之间更深层次的区别是什么。

val myVariable: String get() = activity.myName
Run Code Online (Sandbox Code Playgroud)
val myVariable: String = activity.myName
Run Code Online (Sandbox Code Playgroud)

get()即使我能够从其他类访问这些变量并且对我来说两者的工作原理相同,这又有什么不同呢?

Ten*_*r04 11

get() = 如果您将其移至下一行,将有助于更好地理解它。

val myVariable: String 
    get() = activity.myName
Run Code Online (Sandbox Code Playgroud)

因为那时你会发现你也可以这样做:

val myVariable: String = "something"
    get() = activity.myName
Run Code Online (Sandbox Code Playgroud)

定义属性时会发生两件事。

  1. = "something"或者= activity.myName在属性名称和类型之后是支持字段初始值设定项。当您包含此内容时,将为属性提供一个支持字段,这是一个不可见的变量,可以保存属性要使用的数据,并且表达式用于定义要在支持字段中保存的初始值。

  2. 使用get()创建自定义 getter。这是一个每次访问属性时都会运行的函数,无论该函数返回什么,都是该属性被读取的值。如果省略自定义 getter,则它将使用默认 getter,该默认 getter 仅返回点 1 中支持字段的值。

您不能同时省略字段和自定义 getter,因为这样您将拥有一个默认 getter,没有可检索的支持字段,这是没有意义的。

现在我们可以解释编写这个属性的三种可能的方式:

val myProperty: String 
    get() = activity.myName
// Every time you use this property, it looks up the activity property and finds the
// value of the activity's myName property. So if activity was changed to point to
// something else or myName was changed to point to something else, myProperty will
// always return the latest value when it is used.

val myProperty: String = activity.myName
// This property is initialized with the value that activity.myName holds at the time
// the class is instantiated, and it will always return this same original value even
// if activity or myName changes, because the value of the backing field is never changed.
// The value of the backing field can only be changed if you're using a var property.

val myProperty: String = activity.myName
    get() = activity.myName
// This property behaves like the first one above, but it also has a useless backing
// field that is holding a reference to the original value of activity.myName. Since
// the custom getter doesn't use the backing field, the backing field can never be
// read, so it's useless.
Run Code Online (Sandbox Code Playgroud)

这是同时使用支持字段和自定义 getter 的一种可能的用例。如果您想在支持字段中保留一个恒定值(如上面的第二个示例所示),但会产生一些副作用(例如每次访问时记录某些内容),则可以同时使用两者。该关键字field可以在自定义 getter 中使用来访问支持字段。

val myProperty: String = activity.myName
    get() = field.also { Log.i(TAG, "Retrieved value of myProperty.") }
Run Code Online (Sandbox Code Playgroud)