首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >为什么在生成自动后端字段时必须初始化属性?

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

Stack Overflow用户
提问于 2018-07-12 09:07:23
回答 3查看 2.2K关注 0票数 4

我对属性很陌生,并从java迁移到kotlin。我正在与属性进行斗争,我学到了很多关于的知识,但是初始化这些属性使我感到困惑,什么时候应该初始化它,或者什么时候可以不进行初始化就可以工作。

让我用代码来解释它。下面是在生成后端字段时需要初始化属性的代码,在发布代码之前,请允许我从kotlin官方网站中发布段落。

如果属性使用至少一个访问器的默认实现,或者自定义访问器通过字段标识符引用属性,则将为属性生成支持字段。

下面是代码。

代码语言:javascript
复制
class Employee{
    var data: String // because there are default implementation of get set
                    // so there will be a back-end field.
}

,所以我必须初始化它,否则编译错误.

好的,我可以理解它,因为有人可以访问它,这样就不会有可能产生错误结果的值了。

接下来,我将更多地理解它,因此我添加了自定义getter。

代码语言:javascript
复制
class Employee{
    var data: String
    get() = "default value"
}

这还会生成后端字段,因此编译错误将其初始化为。我可以理解它,因为没有初始化的值,所以编译器抱怨它。

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

如果任何一个人访问,那么默认值就已经存在了,那么为什么编译器仍然抱怨呢?

然后,我再移动一步来实现定制的setter。

代码语言:javascript
复制
class Employee{

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

}

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

最后一个阶段,它运行良好,如下所示。

代码语言:javascript
复制
class Employee{

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

    }

}

现在,我不访问自定义的field getter setter,因此没有后端字段。而且效果很好。

那么最后一个问题是什么时候财产应该被取消呢?当有一个后端字段生成?

EN

回答 3

Stack Overflow用户

发布于 2018-07-12 09:50:12

是的,这并不是编译:

代码语言:javascript
复制
class Employee{
    var data: String
    get() = "default value"
}

但这确实是:

代码语言:javascript
复制
class Employee{
    val data: String
    get() = "default value"
}

因此,也许编译器必须通过声明属性来初始化错误的声明,希望您承认data是您无法更改的。我说也许吧。

下面是编译的部分:

代码语言:javascript
复制
class Employee{

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

    }
}

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

为了让你避免更多的困惑,网上有很多关于Kotlin的解释,你可能会发现很难熟悉这门相对较新的语言,但是要记住,所有的东西都需要你来测试。

我在网页中找到了以下代码:

代码语言:javascript
复制
class User{
    var firstName : String
        get() = field
        set(value) {field = value}

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

如果不是,则表示为可编译的

票数 3
EN

Stack Overflow用户

发布于 2018-07-12 18:48:55

你回答了你自己的问题。当您覆盖getter和setter并且不访问field时,就没有后备字段了。

关于“编译器不够聪明”:get()函数实际上是在运行时运行的,因此编写大量编译器代码只是为了评估返回值是否是静态的,并且应该作为缺省值注入,这对于用例来说太利基了。

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

假设没有定义provider的值,请考虑以下代码:

代码语言:javascript
复制
var data: String
    get() = provider.data

默认值是多少?你想要空吗?空绳子?也许整个对象初始化应该崩溃?为此,需要显式的默认值声明。

这就是lateinit var的思想所在:如果您确信在执行任何get之前都会使用set值,则可以使用这个关键字来防止编译器错误和设置默认值。

票数 3
EN

Stack Overflow用户

发布于 2018-07-12 12:11:28

代码语言:javascript
复制
class Employee{
    var data: String
    get() = "default value"
}

var意味着有一个getter和一个setter。因为您没有编写一个setter,所以您得到了默认的一个,它访问后台字段。因此,有一个支持字段,它需要初始化。

但是如果任何一个人访问它,那么一个默认值就已经存在了,那么编译器为什么还在抱怨呢?

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

我不认为更改规则有什么明显的问题,这样一个字段只需要在getter中访问时才被初始化,并且可能在只有一个访问器使用field时添加警告。但我可能错过了什么,也看不到有多大的好处。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/51301500

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档