我一直在看Kotlin官方教程。我遇到了一个名为支持字段
的主题它说,
Kotlin中的类不能有字段。但是,有时在使用自定义访问器时需要有一个支持字段。出于这些目的,Kotlin提供了一个自动支持字段,可以使用字段标识符访问:
var counter = 0 // the initializer value is written directly to the backing field
set(value) {
if (value >= 0) field = value
}
获得了上述内容
我的问题是,“字段”是否指向计数器变量?
有人可以为我提供一个支持领域的例子,还是用一个理解词来形容我?
答案 0 :(得分:10)
考虑这个课程
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;
}
}
}
答案 1 :(得分:6)
$originalArray = array( 'first', 'second', 'third', 'fourth' );
$newArray= $originalArray;
shuffle( $newArray);
for ($i=0; $i<2; $i++) {
echo $newArray[$i];
}
关键字允许您在自定义设置器中指定值。在kotlin field
中会调用counter = 3
。所以,如果你要定义
set(3)
它将以递归方式调用自身,直到您的堆栈已满并且您的进程崩溃。
var counter=0
set(value){
counter = value
}
关键字直接指定值,而无需再次调用setter。
答案 2 :(得分:3)
Backing Field只是一个为属性生成的字段 仅在类中使用至少一个的默认实现时才在类中 访问者
仅当属性使用getter / setter的默认实现时才会生成Backing字段。如果您使用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中,上面的代码片段将抛出StackOverflow,因为当我们访问或设置属性“first-name”或“last name”时,将调用默认访问者。所以在Kotlin中,“user.firstName =”value“”与Java的“user.setFirstName(”value“)”相同。“
因此,当调用“set(value){firstName =”value“}”时,递归callhappens和编译器抛出异常异常,因为我们在setter中调用setter。
此问题的解决方案是用户支持字段。在Kotlin中,可以使用访问者内部的“field”关键字访问支持字段。请查看下面更正的代码段。
class User{
var firstName : String get() = field
set(value) {
field = value
}
var lastName : String get() = field
set(value) {
field = value}
}
}
答案 3 :(得分:1)
如何运作,让我们通过一个例子来理解,考虑一下这个
class Person {
var name: String = ""
}
如果未指定任何内容,则属性(名称)将使用默认的getter和setter。当然,它可以 被修改为运行您需要的任何自定义行为,而无需更改 现有代码:
因此,如果要将自定义行为设置为name属性,而不是将上面的类修改为此
class Person {
var name: String = ""
get() = field.toUpperCase()
set(value) {
field = "Name: $value"
}
}
如果属性需要在自定义getter或setter中访问自己的值(如此) 例),它需要创建支持字段。可以使用field,a访问它 保留字,并在编译器发现时自动创建 它被使用了。