Kotlin 属性前缀”_“用法

在写Java时候我们对字段命名一般会用m前缀,那么我们在写kotlin时候却没有用这种方式呢?因为kotlin中函数是一等公民,而且可以定义顶层属性和函数,官方也就不再推荐这样的命名规范。并且更多时候称呼kotlin中的变量定义为属性(properties),而不用java中的字段(field)。而kotlin使用"_"作为属性的前缀被称之为后备属性,先解读下官方文档进行学习。

后背字段 Backing fields

Kotlin的类不能有字段。 但是,有时在使用自定义访问器时需要有一个后备字段。 为了这些目的,Kotlin提供了可以使用字段标识符访问的自动备份字段:

var counter = 0 // the initializer value is written directly to the backing field
    set(value) { if (value >= 0) field = value }

这里field标识符只能在属性的set{} get{}中访问。在自定义访问器通过field标识符引用它,则将为属性生成后备字段。 在以下情况下,将不会有后备字段:

val isEmpty: Boolean 
    get() = this.size == 0

后备属性 Backing properties

Kotlin后备属性,下面是官方给的示例。

private var _table: Map<String, Int>? = null
val table: Map<String, Int>
    get() {
        if (_table == null) {
            _table = HashMap() // Type parameters are inferred
        }
        return _table ?: throw AssertionError("Set to null by another thread")
    }

我们经常会在一些代码中看见这样的写法,很多人会表示疑惑,同一个属性为何要用2个变量来持有。一般这些代码有如下特点:

  • 私有的属性有更多可操作的性
  • 对外暴露的属性有更少的可操作性

示例1:

class TestFragment: Fragment() {

    private var _binding: VB? = null

    protected val binding: VB
        get() = requireNotNull(_binding) { "The property of binding has been destroyed." }

    ...
    override fun onDestroyView() {
        super.onDestroyView()
        _binding = null
    }
}

示例2:

class EffectViewModel: ViewModel() {
    private val _effect = MutableSharedFlow<Effect>()
    val effect: SharedFlow<Effect> by lazy { _effect.asSharedFlow() }
}

示例3:

class LiveDataViewModel: ViewModel() {
    private val _liveData = MutableLiveData<Int>()
    val liveData: LiveData<Int> = _liveData
}

后备属性可以更好的构建安全的数据流,因为缩紧了对数据的可操作权限,对外部只提供可读取的权限。这样可以保证数据的安全性,在UDF的数据流中更加容易定位问题和进行数据追踪。

猜你喜欢

转载自blog.csdn.net/Coo123_/article/details/133393783
今日推荐