为什么属性初始值设定项不调用自定义设置器?

2024-04-25

来自Kotlin 文档 https://kotlinlang.org/docs/reference/properties.html#getters-and-setters,允许自定义设置器:

class Test {
  var stringRepresentation: String
    get() = field
    set(value) {
      setDataFromString(value) 
    }

  init {
    stringRepresentation = "test"
  }

  private fun setDataFromString(value: String) { }
}

但是,如果没有自定义 getter,则无法拥有自定义 setter(并从init block):

class Test {
  // Compilation error: "Property must be initialized"
  var stringRepresentation: String
    set(value) {
      setDataFromString(value)
    }

  init {
    stringRepresentation = "test"
  }

  private fun setDataFromString(value: String) { }
}

尽管您可以在没有自定义 setter 的情况下使用自定义 getter,但这里没有问题:

class Test {
  var stringRepresentation: String
    get() = field 

  init {
    stringRepresentation = "test"
  }

  private fun setDataFromString(value: String) { }
}

那么为什么不能使用自定义 setter 和从内部初始化的属性呢?init阻止,为什么init块调用自定义设置器,而属性初始值设定项直接分配,绕过自定义设置器?

class Test {
  var stringRepresentation: String = "" // Does not call custom setter
    set(value) {
      setDataFromString(value)
    }

  init {
    stringRepresentation = "test" // Calls custom setter
  }

  private fun setDataFromString(value: String) { }
}

属性初始值设定项不会调用自定义设置器,因为它们的目的是提供默认值。

与 Java 不同,在 Kotlin 中,不仅局部变量必须在首次访问之前初始化,类属性也必须在首次访问之前初始化。

在 Java 中这是有效的。

public class Test {
    public String str;

    public static void main(String[] args) {
        System.out.println(new Test().str);
    }
}

在 Kotlin 中则不然。

class Parent {
    var str: String?
}

fun main(args: Array<String>) {
    Parent().str
}

因此,自定义 setter 需要通过属性初始值设定项或构造函数来初始化其属性。看一下下面的例子。

class Test {
    var stringRepresentation: String = "a" // Default value. Does not call custom setter
        get() = field
        set(value) {
            println("Setting stringRepresentation property to %s. Current value is %s.".format(value, field))
            field = setDataFromString(value)
        }

    init {
        this.stringRepresentation = "b" // Calls custom setter
    }

    private fun setDataFromString(value: String): String {
        println("Setting stringRepresentation property to %s.".format(value))
        return value
    }
}

fun main(args: Array<String>) {
    Test().stringRepresentation = "c" // Calls custom setter
}

属性 stringRepresentation 初始化为"a"无需调用 setter 即可实例化其类。 然后调用 init 块并将值设置为"b"使用设置器。 然后到"c"使用设置器。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

为什么属性初始值设定项不调用自定义设置器? 的相关文章

随机推荐

  • 错误:查询没有结果数据的目标

    CREATE OR REPLACE FUNCTION chkLogin userid varchar pwd varchar RETURNS BOOLEAN AS BODY DECLARE passed BOOLEAN BEGIN SELE
  • Pandas 更改外汇 DataFrame 的时区

    我们如何更改 Pandas DataFrame 中的时区 我编写了一些简单的代码来读取 1 分钟 EURUSD 数据 日期时间 开盘价 最高价 最低价 收盘价 成交量 示例数据采用 EST 时区 我需要将其转换为 UTC df tz con
  • ImageMagick 在命令行中工作,但是当 php 中的 exec() 时,它返回 5 并显示“不兼容的库版本”

    我在 OS X 上使用 MAMP 以及 Macports 的 php 5 3 6 和 ImageMagick 命令行 遇到了一个奇怪的问题 当我从 CLI 运行识别命令时 它工作正常 但是当我使用运行完全相同的命令时exec 它返回一个值代
  • Invoke-WebRequest 设置超时

    我有一个长时间运行的网页 需要 Powershell 来调用 我每晚从任务管理器运行它 内容如下 powershell Command Invoke WebRequest https www example com longrunningt
  • 使用帮助库管理器和 WiX 安装帮助

    我试图通过使用 WiX 运行 Sandcastle 帮助文件生成器在构建我的 Sandcastle 项目后创建的 HelpLibraryManagerLauncher 将我自己的帮助文件添加到 Visual Studio 2010 的帮助库
  • 确保始终捕获异常

    C 中的异常不需要被调用函数捕获 没有编译时错误 因此 是否使用 try catch 来捕获它们取决于开发人员的判断 与 Java 不同 有没有一种方法可以确保调用函数始终使用 try catch 捕获抛出的异常 No See 务实地看待异
  • Google PubSub / Gmail Webhook:发送电子邮件时始终从 PubSub 接收多个 POST 请求

    我设置了一个 webhook 它使用 Google Cloud PubSub API 和 Java 中的 Gmail API 监听和处理 Gmail 中收件箱和发送文件夹中的更改 我看到的问题是 当我向另一个用户发送消息时 PubSub 似
  • 我可以在调用者处将函数参数默认为 __FILE__ 的值吗?

    在 C 中 我可以为函数提供一个默认参数吗 PRETTY FUNCTION FILE and LINE 在调用者处定义 而不是在不使用宏的情况下在头文件中提供默认值的地方 您不能 但您可以通过附加宏来实现此行为 例如 DEFINE THRO
  • 条件合并表

    我有 2 张桌子 Time X1 8 1 2013 56 9 1 2013 14 10 1 2013 8 11 1 2013 4 12 1 2013 78 Time X2 8 1 2013 42 9 1 2013 44 10 1 2013
  • 使用 Tesseract OCR 和 python 进行数字识别

    我使用 Tesseract 和 python 读取数字 从能量计 除了数字 1 之外 一切都运行良好 Tesseract 无法读取 1 数字 This is the picture I send to tesseract tesseract
  • 仅调整 matplotlib 中两个子图之间的距离

    我有 3 个子图 3 行和 1 列 我们可以用fig subplots adjust hspace 0 2 调整子图之间的距离 这将改变所有情况下子图之间的距离 地块 1 311 和地块 2 312 以及地块 2 312 和地块 3 313
  • R 堆积百分比频率直方图以及基于聚合数据的百分比

    I believe my question is very similar to this post https stackoverflow com questions 34903368 how to center stacked perc
  • sqlite 语句中返回的行数

    有没有简单的方法来获取 sqlite 语句返回的行数 我不想首先经历执行 COUNT 的过程 谢谢 每次致电时sqlite step 将变量加 1 如果你想要行数提前 那么就没有简单的方法了
  • 当对象的状态发生变化时触发Java中的事件

    我有一个 Java 对象 其状态随着时间的推移而变化 当对象中的某个字段达到特定值时 我希望触发外部事件 我知道 Swing 通过监听器处理这种模式 并且我在这个项目中使用 Swing 但我不确定哪种监听器适用于这种情况 用户不会更改对象的
  • Excel VBA 自动生成电子表格

    我和我的朋友目前有一个主电子表格 我需要定期将其分解为较小的电子表格 这曾经是一个手动过程 但我想将其自动化 我在 VBA 中创建了一个三步解决方案 它将帮助我完成以下任务 将相关过滤器应用于电子表格 将过滤后当前可见的数据导出到新电子表格
  • Sphinx——结合自动模块和自动类

    除非我错过了什么 斯芬克斯的automodule只会记录模块的成员 而不记录该模块中定义的类的属性 有办法吗自动地得到的行为automodule and autoclass以这样的方式组合 我可以自动获取模块成员的文档and在该模块中找到的
  • java - Google Play 游戏服务

    Google Play 游戏服务正在测试 public class MainActivity extends BaseGameActivity public void onCreate Bundle savedInstanceState s
  • 如何在javascript中将两个大数相加?

    我有两个文本框 每个将接受最多千位数字的输入 现在我想将这两个数字相加 我的问题是我应该使用什么数据类型来存储结果 我已经尝试过这个 但我得到的结果是指数形式的 如何存储结果并显示 这是另一种解决方案 因为它更快 更干净 function
  • Kendo 网格列宽度 + 可滚动

    我正在尝试从 JavaScript 绑定到可滚动剑道网格 但在列宽方面遇到了一些问题 这fiddle http jsfiddle net mnTGm 1 演示了问题 问题末尾的代码 我在 html 中指定标头并向其中一个标头添加宽度 然后
  • 为什么属性初始值设定项不调用自定义设置器?

    来自Kotlin 文档 https kotlinlang org docs reference properties html getters and setters 允许自定义设置器 class Test var stringRepres