Kotlin 使用 getter 作为只读变量
Kotlin using getter for read-only variable
我们对 val 变量使用 get() 有什么原因吗?
我觉得下面的代码没有必要
private val context: Context get() = ApplicationProvider.getApplicationContext<Context>()
所以我将其更改为
private val context: Context = ApplicationProvider.getApplicationContext<Context>()
对只读变量使用 get() 会有什么不同?
对于 getter 不需要定义 get() 但需要 setter case set。
从 Kotlin 1.1 开始,如果可以从 getter 推断出 属性 类型,则可以省略它:
val isEmpty get() = this.size == 0 // has type Boolean
如果您需要更改访问器的可见性或对其进行注释,但不需要更改默认实现,您可以在不定义其主体的情况下定义访问器:
var setterVisibility: String = "abc"
private set // the setter is private and has the default implementation
var setterVisibility: String = "abc"
private set // the setter is private and has the default implementation
有关详细信息,请参阅 Properties and Fields
IntelliJ Amiya 在评论中给出的 link 包含所有必要的信息,但要特别回答你的问题:
get() = ...
每次访问时都会调用 ApplicationProvider.getApplicationContext<Context>()
;只是 = ...
会调用它一次并存储,然后 return 访问时存储的值。您想要哪一个或它们是否有效等效(因为例如主体总是 return 相同的值并且足够快)取决于上下文。
您正在处理两种不同的属性声明方式:
属性 带有支持字段
如果你声明一个 属性 context
并像这样分配它:
private val context: Context = ApplicationProvider.getApplicationContext<Context>()
您创建了一个 property with backing field。
ApplicationProvider.getApplicationContext<Context>()
在实例化 class 时计算一次。由于 context
是不可变的 (val
),因此每次 return 编辑相同的值(由函数调用分配)。
属性 没有支持字段
如果你这样声明context
private val context: Context get() = ApplicationProvider.getApplicationContext<Context>()
您创建了一个没有支持字段的 属性。 ApplicationProvider.getApplicationContext<Context>()
将在您每次访问 context
时进行评估。 getter 编辑的值 return 可以更改,具体取决于函数的转发调用 return 是否有所不同。
用什么?
因此,这取决于您的用例,但在这种特殊情况下,我建议您使用没有支持字段变体的 属性,原因有两个:
- 您不能确定
ApplicationProvider.getApplicationContext<Context>()
将始终 return 相同的值,至少文档没有明确提及
- 转发函数调用不会对性能产生重大影响
我们对 val 变量使用 get() 有什么原因吗?
我觉得下面的代码没有必要
private val context: Context get() = ApplicationProvider.getApplicationContext<Context>()
所以我将其更改为
private val context: Context = ApplicationProvider.getApplicationContext<Context>()
对只读变量使用 get() 会有什么不同?
对于 getter 不需要定义 get() 但需要 setter case set。
从 Kotlin 1.1 开始,如果可以从 getter 推断出 属性 类型,则可以省略它:
val isEmpty get() = this.size == 0 // has type Boolean
如果您需要更改访问器的可见性或对其进行注释,但不需要更改默认实现,您可以在不定义其主体的情况下定义访问器:
var setterVisibility: String = "abc"
private set // the setter is private and has the default implementation
var setterVisibility: String = "abc"
private set // the setter is private and has the default implementation
有关详细信息,请参阅 Properties and Fields
IntelliJ Amiya 在评论中给出的 link 包含所有必要的信息,但要特别回答你的问题:
get() = ...
每次访问时都会调用 ApplicationProvider.getApplicationContext<Context>()
;只是 = ...
会调用它一次并存储,然后 return 访问时存储的值。您想要哪一个或它们是否有效等效(因为例如主体总是 return 相同的值并且足够快)取决于上下文。
您正在处理两种不同的属性声明方式:
属性 带有支持字段
如果你声明一个 属性 context
并像这样分配它:
private val context: Context = ApplicationProvider.getApplicationContext<Context>()
您创建了一个 property with backing field。
ApplicationProvider.getApplicationContext<Context>()
在实例化 class 时计算一次。由于 context
是不可变的 (val
),因此每次 return 编辑相同的值(由函数调用分配)。
属性 没有支持字段
如果你这样声明context
private val context: Context get() = ApplicationProvider.getApplicationContext<Context>()
您创建了一个没有支持字段的 属性。 ApplicationProvider.getApplicationContext<Context>()
将在您每次访问 context
时进行评估。 getter 编辑的值 return 可以更改,具体取决于函数的转发调用 return 是否有所不同。
用什么?
因此,这取决于您的用例,但在这种特殊情况下,我建议您使用没有支持字段变体的 属性,原因有两个:
- 您不能确定
ApplicationProvider.getApplicationContext<Context>()
将始终 return 相同的值,至少文档没有明确提及 - 转发函数调用不会对性能产生重大影响