【问题标题】:Get and set methods which depends on other field获取和设置依赖于其他字段的方法
【发布时间】:2018-10-04 20:30:23
【问题描述】:

我不知道如何在标题中表达这一点。什么是 Kotlin 等价于 Java 代码。我所有的尝试都以错误或 stackoverflow 告终。使用 Jackson 进行序列化时会发生这种情况。

public class Test {
    private String test1;
    private String test2;

    public String getTest1() {
        return test1;
    }

    public void setTest1(String test1) {
        this.test1 = test1;
    }

    public String getTest2() {
        return test2!=null? test2:test1;
    }

    public void setTest2(String test2) {
        this.test2 = test2;
    }
}

Kotlin 代码如下,

class Test(var test1: String? = "") {
    var test2: String?
        get() = if (StringUtils.isNotEmpty(test2)) test2 else test1
        set(test2Val) {
            test2 = test2Val
        }
}

我缺少哪些 Kotlin 基础知识?

【问题讨论】:

    标签: kotlin jackson


    【解决方案1】:

    test2 最终会调用 getter。您可以查看生成的 Java 代码以供参考。

    在自定义 getter 和 setter 中,您使用 field 代替。所以正确的代码是:

    class Test(var test1: String? = "") {
        var test2: String?
            get() = if (StringUtils.isNotEmpty(field)) field else test1
            set(test2Val) {
                field = test2Val
            }
    }
    

    注意:这会导致第二个问题。您还没有初始化变量,这与 vars 有关系。如果您有一个 val 和一个返回其他内容的自定义 getter(即 val x = ... get() = someOtherVar,则不会产生编译器错误)。不过这不适用于vars。但是,在您的情况下,使用= null(或= "")就足够了。

    但是既然你说你得到了 StackOverflowErrors 而不是一个与缺乏初始化相关的错误,我猜你确实初始化了它,但只是没有将它包含在 MCVE 中。但如果你没有,那值得注意。


    此外,Kotlin 有 isNotEmpty()isNotBlank() 之类的方法,它们取代了对 StringUtils.isNotEmpty() 的需求,并且被称为 field.isNotEmpty()。请注意,在这里您要执行if(field?.isNotEmpty() == true) ...,因为您最终会得到一个可为空的布尔值。这也意味着如果字段为空或为空,它将返回 test1。喜欢的也可以加isNotBlank

    如果 setter 与生成的 setter 完全相同,则无需手动声明它们。如果您这样做,像 IntelliJ 这样的 IDE 也会警告您,并建议您删除它。如果它是默认设置器,是否手动声明它并不重要,但它可以帮助您编写更少的代码。

    【讨论】:

    • 我错过了文档中的这一部分,“可以使用字段标识符在访问器中引用此支持字段”。在 Kotlin 中这样做有什么理由吗?其他语言中是否有类似的内容?
    • Kotlin 的工作方式与其他语言不同。在 Java 中,您直接拥有字段,并使用它们进行处理; getter、setter 等。Kotlin 实际上使用属性(/变量),而不是字段。正如您所提到的,可以使用field 关键字访问字段,但这里的关键是系统。我假设还有其他编程语言可以做同样的事情,但 Java 没有。它主要是关于语言特性的设计,所以它不像语言的标准库中的方法。
    【解决方案2】:
    class Test(var test1: String? = "") {
        var test2: String?
            get() = if (StringUtils.isNotEmpty(test2)) test2 else test1
            set(test2Val) {
                test2 = test2Val // here you are recursively setting the value of test2              
            }
    }
    

    如果你想给backing field赋值,应该是

    field = test2Val
    

    但在这种情况下,setter 将毫无意义,因为如果您不声明它,它将具有相同的行为。 这个想法是field 是私有属性,getset 是setter。您可以选择从 getter 中返回什么,以及如何处理传递给 setter 的值。

    另一个问题是 test2 需要一个初始值,在 Java 中它会默认初始化为 null 但在 Kotlin 中你必须显式地分配一个初始值。因此,例如使用空字符串:

    class Test(var test1: String? = "") {
        var test2: String? = ""
            get() = if (StringUtils.isNotEmpty(test2)) test2 else test1
    }
    

    【讨论】:

      猜你喜欢
      • 2016-06-18
      • 1970-01-01
      • 2022-01-14
      • 2020-08-07
      • 1970-01-01
      • 1970-01-01
      • 2014-12-01
      • 1970-01-01
      • 2023-03-25
      相关资源
      最近更新 更多