在写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的数据流中愈加简单定位问题和进行数据追寻。