【问题标题】:Setting a kotlin extension设置 kotlin 扩展
【发布时间】:2016-12-19 12:47:12
【问题描述】:

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

在我的程序中,我有一个名为 Submission 的 java 类,我想创建一个名为 categories 的 kotlin 扩展 - 一个 ArrayList - 所以我把它做成了这样。

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

但是,每当我尝试设置一个类别时,程序就会崩溃,并出现这样的 stackOverflowError:

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 扩展的正确语法。所以我真的不确定我应该在哪个方向解决这个问题。也许我真的应该只使用普通的旧继承?

谢谢。

【问题讨论】:

  • 您没有在 setter 中的 getter 中定义任何自定义逻辑,那么为什么需要它们?问题是由于setter声明不正确,this.categories = categories会调用set()方法,导致死循环。
  • @Egor 啊,这很有意义。我定义 get 和 set 方法的原因是因为它拒绝在没有 get 方法和 return 语句的情况下进行编译。我认为这对于一组也是一样的,并且也这样做了。我将尝试删除设置的逻辑,看看会发生什么。

标签: kotlin kotlin-extension


【解决方案1】:

您的代码抛出StackOverflowError,因为它递归地调用自己。 this.categories 只是调用它已经在其中的 getter,this.categories = categories 调用它已经在其中的 setter。

扩展属性只是一对(扩展)getter 和 setter 的语法糖。在属性访问器(即 getter 和 setter)内,您只能访问接收者类已经可以访问的 publicly 内容。如果它有公共字段,您可以访问它们,但是您不能定义新字段。如果您想保存额外的状态,但该类没有相应的 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 不是该程序中的公共字段,我试图定义一个新字段。所以我想这是根本问题。
  • 我完全同意这个答案,但可能值得一提的是,虽然扩展不能修改类以添加支持字段,但额外的状态仍然可以存储在类之外的某个地方,并且代表可以在这里提供帮助.有关此解决方法的更多详细信息,请参阅:stackoverflow.com/a/36511438/2196460
  • @hotkey 感谢您的链接。可以肯定的是,这也适用于 java 类
  • @nmu,是的,它会的,你也可以为 Java 类定义 Kotlin 扩展。如果您需要在 Java 中使用这些扩展,它们可以作为静态函数可见。例如,在KotlinFile.kt 中为MyClass 定义的tag 扩展将被视为KotlinFileKt.getTag(MyClass $receiver) 和类似的setter。
  • 我的答案中的代码 sn-p 实际上具有 Java 类。
猜你喜欢
  • 2020-09-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多