Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/kotlin/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Kotlin 为什么在生成自动后端字段时必须初始化属性_Kotlin - Fatal编程技术网

Kotlin 为什么在生成自动后端字段时必须初始化属性

Kotlin 为什么在生成自动后端字段时必须初始化属性,kotlin,Kotlin,我不熟悉properties,从java搬到kotlin。我正在与属性作斗争,我对它了解了很多,但是初始化属性让我很困惑,什么时候应该初始化,什么时候不初始化就可以工作。 让我用代码来解释一下。下面是生成后端字段时需要初始化属性的代码,在发布代码之前,请允许我发布 如果属性使用 至少一个访问器的默认实现,或者 自定义访问器通过字段标识符引用它 下面是代码 class Employee{ var data: String // because there are default imple

我不熟悉properties,从java搬到kotlin。我正在与属性作斗争,我对它了解了很多,但是初始化属性让我很困惑,什么时候应该初始化,什么时候不初始化就可以工作。

让我用代码来解释一下。下面是生成后端字段时需要初始化属性的代码,在发布代码之前,请允许我发布

如果属性使用 至少一个访问器的默认实现,或者 自定义访问器通过字段标识符引用它

下面是代码

class Employee{
    var data: String // because there are default implementation of get set
                    // so there will be a back-end field.
}
因此我必须初始化它,否则编译错误。

好的,我可以理解为有人可以访问它,因此不会有任何可能产生错误结果的值。

接下来我将进一步了解它,所以我添加了自定义getter

class Employee{
    var data: String
    get() = "default value"
}
这也会生成后端字段,因此编译错误将其初始化。我可以理解为没有初始化值,所以编译器会抱怨它

可能是编译器还不够聪明,无法通过自定义getter检查是否存在为该属性提供结果的值,所以不要抱怨初始化,只需在需要时返回该值即可

但若有人访问它,那个么默认值已经存在,那个么编译器为什么还要抱怨呢?

然后,我进一步实现自定义setter

class Employee{

    var data: String
    get() = "default value"
    set(value){
        field = value
    }

}
仍然有后端字段,因为我们访问了
字段
,所以编译器生成后端字段。 同样的错误,应该初始化

然后到了最后一个阶段,它工作得很好,如下所示

class Employee{

    var data: String
    get() = "default value"
    set(value){

    }

}
现在我没有在custom
getter
setter
中访问
字段
,因此没有后端字段。而且效果很好


那么,最后一个问题是什么时候应该对财产进行初始化?当生成后端字段时?

是,这不会编译:

class Employee{
    var data: String
    get() = "default value"
}
但这确实:

class Employee{
    val data: String
    get() = "default value"
}
因此,可能编译器必须通过声明属性来初始化错误的声明,希望您承认
数据
是您无法更改的。我说也许吧
现在编译的部分是:

class Employee{

    var data: String
    get() = "default value"
    set(value){

    }
}
这就是您明确承认无论发生什么,我都不会将值设置为
data
,这就是编译器感觉良好的原因

为了避免更多的困惑,互联网上有很多关于Kotlin的解释,你可能会发现很难熟悉这门相对较新的语言,但请记住,一切都需要你来测试
我在网页中找到以下代码:

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

    var lastName : String
        get() = field
        set(value) {field = value}
}
如果它不是可编译的,则表示为可编译的

class Employee{
    var data: String
    get() = "default value"
}
var
意味着既有一个getter,也有一个setter。因为您没有编写setter,所以得到了默认setter,它访问backing字段。因此有一个支持字段,需要对其进行初始化

但若有人访问它,那个么默认值已经存在,那个么编译器为什么还要抱怨呢

因为这使得规则更简单:所有带有支持字段的属性都必须初始化。这可能是因为Java中的字段不必初始化,这是一个已知的bug源。我想说的是,它还避免了一个可能的bug,因为您可能并不希望setter的结果永远无法访问,但是初始化并不能解决这个问题


我看不出更改规则有任何明显的问题,以便在getter中访问字段时只需要初始化字段,并且可能在只有一个访问者使用
字段时添加警告。但我可能遗漏了一些东西,而且也看不出这样做有什么好处。

你回答了自己的问题。当您重写getter和setter,并且不访问
字段时,没有支持字段

关于您的“编译器不够聪明”:
get()
函数实际上是在运行时运行的,因此编写大量编译器代码只是为了评估返回值是否是静态的,是否应该作为默认值注入,这在用例中太小了

如果您的getter依赖于另一个稍后才初始化的字段,这将导致很多关于默认值应该是什么的混淆

考虑此代码,假设未定义
提供程序
的值:

var data: String
    get() = provider.data
默认值是什么?你想要一个空的吗?空字符串?也许整个对象初始化应该崩溃?为此,需要显式的默认值声明


这就是
lateinitvar
的思想产生的原因:如果您确定在执行任何
get
之前将
设置值,您可以使用此关键字来防止编译器错误和设置默认值。

这就是您明确承认无论发生什么,我都不会为数据设置值的地方。
为什么我必须承认它?那么var的需求是什么呢?我认为编译器方面有问题,或者有一件我不知道的深层次的事情,
var
的需求是显而易见的:变量。如果属性为只读,则它不是变量。只有通过声明一个空的setter来承认这不是一个变量,编译器才会接受
var
(尽管它是无用的)。它有文档记录吗?或者您正在描述您的经验?文档在这里:,但是它没有扩展到适合我们所有的问题,所以练习、猜测和更多的练习是我的解决方案。您应该尝试data class,它与java bean类相同。因此,您不需要创建getter、setter和所有内容。@VijayMakwana我不是问解决方案,只是问r