Kotlin Backing Field

备用字段?
幕后字段?
支持字段?
后端域变量?
翻译这么多种,其实都是一个意思 Backing Field

找到一些关于他的描述:

  • Kotlin中的类不能有field。但是,有时在使用自定义访问器时必须有一个 backing field 。为此,Kotlin提供了一个自动backing field,可以使用 field 标识符来访问。

  • Backing field is an autogenerated field for any property which can only be used inside the accessors(getter or setter) and will be present only if it uses the default implementation of at least one of the accessors, or if a custom accessor references it through the field identifier.This backing field is used to avoid the recursive call of an accessor which ultimately prevents the StackOverflowError.

  • 幕后字段是一个自动生成的字段,它仅仅可以被用在拥有至少一个默认访问器 (getter、setter) 、或者在自定义访问器中通过 field 标识符修饰的属性中。幕后字段可以避免访问器的自递归而导致程序崩溃的 StackOverflowError 异常。

那么这里有一些关于field的特点:

  • field标识符只允许在属性的访问器函数内使用。
  • 如果你显式地引用或者使用默认的访问器实现,编译器会为属性生成field。
  • 如果你提供了一个自定义的访问器实现并且没有使用field,将不会生成field。
  • 访问属性的方式不依赖于它是否含有field。

在setter函数体中,使用了特殊标记符field来访问字段的值
在getter中,只能读取该值。
在setter中,既能读取也能修改它。

//使用field关键字
public var fieldProp = ""
    get() = field
    set(value) {
        field = value
    }
//自定义不使用field 不生成:
val isEmpty: Boolean
    get() = this.size == 0
//默认访问器 生成:
val Foo.bar = 1

如果在类中定义一个成员变量,kotlin将自动生成默认的setter/getter方法。
kotlin声明get/set的方式为

  var name: String? = null
        set(value) {
            field = value
        }
        get() = field

这里使用了field,如果不使用field,会这么写:

  var name: String? = null
        set(value) {
            name = value
        }
        get() = name

但是这么写,对这个属性进行赋值并取值时出现了一些问题:


图片1.png

在setter方法中对属性进行赋值和取值时,会调用自身,出现了递归调用。

这个时候field就可以解决这个问题了,backing field的作用域在当前属性的setter/getter方法中,以中间变量的形式,来解决了递归问题。

在拓展属性中

在拓展属性中,是没有field这个字段的


图片2.png

转换一下写法


图片3.png

按照正常的写法,这里报错。说明拓展属性没有field。
如果把这个拓展常量变成属性,会提示属性必须初始化:


图片4.png

那我们直接初始化试试


图片5.png

直接赋值进行初始化又报错了: 拓展属性不能初始化,因为他没有支持字段 (backing field)。
为什么拓展属性不能初始化?这个问题可以转换为 为什么拓展属性没有支持字段?

官方说:

实际上,扩展并不会真正地往类中插入成员变量。因此,我们没有一个有效的方式让一个扩展属性拥有backing field,这就是扩展属性不允许被初始化的原因。

那么拓展属性到底是什么?
Kotlin 可以对一个类的属性和方法进行扩展,且不需要继承或使用装饰器模式。扩展是一种静态行为,对被扩展的类代码本身不会造成任何影响。

因为不会对类的代码本身造成任何影响,所以扩展不会真正的往类中插入成员变量。

field的作用域是当前属性的访问器,而当前属性是与某个类的实例对应的,所以类中并没有这个属性,也就没有一个有效的方式让这个属性拥有backing field了。

  • 有field和没有field的属性有什么区别?

访问属性的方式不依赖于它是否含有field,如果你显式地引用或者使用默认的访问器实现,编译器会为属性生成field。如果你提供了一个自定义的访问器实现并且没有使用field,支持字段将不会被呈现出来。

有时候不需要修改访问器的默认实现,但是需要修改它的可见性:

class LengthCounter {
  var counter: Int = 0
    private set //这个属性不能在所在类外部被修改
  fun addWord(word: String) {
    counter += word.length
  }
}

在接口中

在接口中,可以包含具有setter/getter的属性,只要他们没有引用一个backing field,
backing field需要在接口中存储状态,而这是不被允许的


图片6.png

图片7.png
支持属性:功能与backing field相似,能达到相同的效果:
private var _table: Map<String, Int>? = null
public val table: Map<String, Int>
    get() {
        if (_table == null) {
            _table = HashMap() // 参数类型是自动推导
        }
        return _table ?: throw AssertionError("Set to null by another thread")
    }
参考

https://medium.com/@agrawalsuneet/backing-field-in-kotlin-bd9c2d5b6da5
https://juejin.im/post/5a79c053f265da4e6e2bad37
https://blog.csdn.net/Strange_Monkey/article/details/82707242

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,752评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,100评论 3 387
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,244评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,099评论 1 286
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,210评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,307评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,346评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,133评论 0 269
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,546评论 1 306
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,849评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,019评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,702评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,331评论 3 319
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,030评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,260评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,871评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,898评论 2 351

推荐阅读更多精彩内容