【问题标题】:Kotlin explain me about Backing FieldsKotlin 向我解释了支持字段
【发布时间】:2017-12-06 16:25:05
【问题描述】:

我一直在看 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
    }

我从this official link得到以上信息

我的问题是,“字段”是否指向计数器变量?

有人可以为我提供一个支持领域的例子或用一个容易理解的词来描述我吗?

【问题讨论】:

  • 为什么开头为负数?
  • 一方面,您发布的代码并不是整个代码示例。人们不应该去外部链接来获得全貌。是的,看起来 field 是一个特殊的关键字,有助于改变 setter。

标签: android kotlin kotlin-android-extensions


【解决方案1】:

考虑这个类

class SomeClass {
    var counter: Int = 0
        set(value) {
            if (value >= 0) field = value
        }
}

在 Android Studio 中,转到 Main menu -> Tools -> Kotlin -> Show Kotlin Bytecode 并在 Kotlin 字节码面板中单击 Decompile

您看到的是 Java 中的等效代码。

public final class SomeClass {
   private int counter;

   public final int getCounter() {
      return this.counter;
   }

   public final void setCounter(int value) {
      if(value >= 0) {
         this.counter = value;
      }
   }
}

【讨论】:

  • 您也为找出其他问题铺平了道路...非常感谢。
【解决方案2】:

field 关键字允许您在自定义设置器中分配值。在 kotlin 中,counter = 3 将调用 set(3)。所以如果你定义

var counter=0
set(value){
    counter = value
}

它会递归调用自己,直到您的堆栈已满并且您的进程崩溃。 field 关键字直接赋值,无需再次调用setter。

【讨论】:

    【解决方案3】:

    支持字段只是将为属性生成的字段 仅当它使用至少一个的默认实现时才在一个类中 访问者的数量

    仅当属性使用 getter/setter 的默认实现时才会生成支持字段。如果您看到以下代码的视角为Java。它看起来是正确的。但是在“kotlin”中它会抛出异常。

      class User{ 
           var firstName : String //backing field generated
          get() = firstName 
          set(value) {
               firstName = value
          } 
          var lastName : String //backing field generated 
          get() = lastName 
          set(value) {
               lastName = value
          }
          val name : String //no backing field generated 
          get() = "{$firstName $lastName}" 
          var address : String = "XYZ" //^because there is no default //^implementation of an accessor 
     }
    

    在 Kotlin 中,上面的代码 sn-p 将抛出 StackOverflow,因为当我们访问或设置属性“first-name”或“last name”时,将调用默认访问器。因此,在 Kotlin 中,“user.firstName = "value"” 与 Java 的“user.setFirstName("value")”相同。

    因此,当调用“set(value) {firstName = "value"}”时,会发生递归调用,编译器会抛出 Exception 异常,因为我们在 setter 内部调用 setter。

    此问题的解决方案是用户支持字段。在 Kotlin 中,可以使用访问器中的“field”关键字访问支持字段。看看下面更正后的代码 sn-p。

     class User{ 
          var firstName : String get() = field 
          set(value) {
               field = value
          } 
          var lastName : String get() = field 
          set(value) {
               field = value} 
          }
     }
    

    【讨论】:

      【解决方案4】:

      它是如何工作的,让我们通过一个例子来理解,考虑一下这个

      class Person {
         var name: String = ""
      }
      

      如果未指定任何内容,则属性(name) 使用默认的 getter 和 setter。它当然可以, 进行修改以运行您需要的任何自定义行为,而无需更改 现有代码:

      所以如果想将自定义行为设置为 name 属性而不是我们将上面的类修改为这个

      class Person {
      
         var name: String = ""
         get() = field.toUpperCase()
         set(value) {
           field = "Name: $value"
        }
      
      
      }
      

      如果属性需要在自定义 getter 或 setter 中访问自己的值(如在此 case),它需要创建一个支持字段。它可以通过使用字段来访问,a 保留字,编译器发现时会自动创建 它正在被使用。

      【讨论】:

        猜你喜欢
        • 2017-08-30
        • 2020-08-12
        • 1970-01-01
        • 2016-12-10
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-02-11
        相关资源
        最近更新 更多