从Java接口实现Kotlin属性

5

考虑以下Java接口

interface Foo {
    String getValue();
}

在Kotlin中,get/set函数转换为属性,因此我期望实现看起来像这样。
class FooImpl : Foo {
    val value: String get() = "Hello, World!"
}

但是我必须按照接口中的方法实现它。

class FooImpl {
    override fun getValue(): String {
        return "Hello, World!";
    }
}

为什么?
1个回答

7
Kotlin在方法和属性之间进行了明确的区分。它们并不被视为同一种东西;只是因为JVM没有本地支持属性,所以它们最终都会编译成方法。因此,方法不能实现属性,因为它们根本不同。
无法使用属性实现Java getter的原因与无法使用override val x: String实现Kotlin定义的fun getX(): String相同,它们不兼容。
这里的混淆似乎源于Kotlin允许您使用类似属性的语法访问Java getter,即如果类在Java中定义,则val foo = obj.x等同于val foo = obj.getX()
这严格是一个单向关系,使得与Java代码互操作的Kotlin代码稍微更加紧凑和“Kotlin式”;这种语法快捷方式不扩展到将该方法实现为属性。
此外,如果您将一个方法实现为属性,那可能会导致奇怪的效果。可以说,它既是一个方法,又是一个属性,这不仅很奇怪,而且可能会在语言中引起许多其他意外行为和边缘情况。(例如,在使用反射时如何处理?)

我曾认为 Kotlin 中的属性只是 get/set 函数的语法糖,就像 C# 中一样。如果您尝试创建一个名为 string Foo { get; } 的 C# 类属性,然后尝试定义一个名为 string get_Foo() 的方法,编译器将抱怨您已经定义了该方法。那么,到底是什么使 Kotlin 属性与 get/set 方法不同呢? - Matthew Layton
1
编程语言不是单一的模型。有描述代码中可描述的特性和概念的“语言模型”。编译后的模型(JVM)可能完全不同。语言模型中的内容(例如泛型)可能会有所不同,也可能相反。该语言将方法、属性和构造函数视为不同的事物。是的,它们都可以包含代码,但它们的能力、规则和用途不同。编译后,它们都被映射到简单的JVM方法,因为区别只在语言中有用;JVM本身并不关心。 - BambooleanLogic
1
那么为什么我们需要它们呢?好吧,我们不需要;Java已经在没有它们的情况下运行了25年以上。但是它们确实有许多好处。首先,声明字段和访问器更加紧凑。第二,将字段和访问器统一为单个概念,以简单的方式解决了底层封装和兼容性问题。第三,能够将获取/设置数据的方法引用称为一个单独的东西——属性,而不是两个方法引用,这有助于高级功能,如序列化或注入。第四,属性委托非常棒。我可以继续说下去,但是我已经用完了字符数。 - BambooleanLogic

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接