设置 Kotlin 扩展函数

3

我不确定是否可以像Java对象一样设置Kotlin扩展。

在我的程序中,我有一个名为Submission的Java类,我想创建一个称为categories的Kotlin扩展 - 一个ArrayList - 所以我像这样创建它。

var Submission.categories: ArrayList<String>
    get() {
        return this.categories
    }
    set(categories){
        this.categories = categories
    }

然而,每当我尝试设置一个类别时,程序就会崩溃,并出现如下的堆栈溢出错误:
ERR: stack=java.lang.StackOverflowError: stack size 8MB
             at com.....setCategories(Extensions.kt:0)
             at com.....setCategories(Extensions.kt:19)
             at com.....setCategories(Extensions.kt:19)
             at com.....setCategories(Extensions.kt:19)
             at com.....setCategories(Extensions.kt:19)
             at com.....setCategories(Extensions.kt:19)

这似乎是声明Kotlin扩展的正确语法。因此,我不确定我应该采取什么方向来解决这个问题。也许我应该只使用普通的继承?谢谢。

你在getter和setter中没有定义任何自定义逻辑,那么你为什么需要它们呢?问题是由于错误的setter声明引起的,this.categories = categories将调用set()方法,这将导致无限循环。 - Egor
@Egor 那很有道理。我定义get和set方法的原因是,如果没有get方法和返回语句,它就无法编译。我以为设置也是一样的,所以也这样做了。我将尝试删除set逻辑,看看会发生什么。 - nmu
1个回答

4
你的代码会抛出一个StackOverflowError,因为它在递归调用自身。this.categories只是调用已经存在的getter方法,而this.categories = categories则调用了已经存在的setter方法。
扩展属性只是一对(扩展)getter和setter的语法糖。在属性访问器中(即getter和setter),你只能访问接收类中已经公开的内容。如果它有公共字段,你可以访问它们,但是你不能定义新字段。如果你想保存附加状态但类没有API支持,那么你就没办法了。
可变扩展属性通常会重定向到现有的可变函数。以下是一个例子。
//java
class Foo {
    private List<String> items;

    public String myItems() {
        return items;
    }
}


//kotlin
var Foo.firstItem: String
    get() = myItems()[0]
    set(value) {
        myItems()[0] = value
    }

即使我修改了我的getter和setter以避免递归调用 - 正如你所指出的那样。StackOverflowError仍然会移动到get()。但是,如果我正确理解了你的帖子,这本来就不应该起作用,因为categories不是此程序中的公共字段,我试图定义一个新字段。所以我想这就是根本问题。 - nmu
4
我完全同意这个答案,但值得一提的是,虽然扩展方法不能修改类以添加后备字段,但是附加状态仍然可以存储在类外部的某个地方,而代理可以在这里提供帮助。有关此解决方法的详细信息,请参见:https://dev59.com/hloV5IYBdhLWcg3wPcxv#36511438 - hotkey
@hotkey,感谢提供链接。为了确认,这个方法也适用于Java类吗? - nmu
1
@nmu,是的,您可以定义Java类的Kotlin扩展。如果您需要在Java中使用这些扩展,它们将作为静态函数可见。例如,在“KotlinFile.kt”中定义的“MyClass”的“tag”扩展将被视为“KotlinFileKt.getTag(MyClass $receiver)”以及类似的setter。 - hotkey
@hotkey 哦,太好了。我现在要试一下。感谢您的帮助。 - nmu
1
我的回答中的代码片段实际上包含了一个Java类。 - Kirill Rakhman

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