在 Kotlin 的数据类中,在调用超类构造函数之前访问函数。

16

我正在使用Kotlin中的数据类来显著减少我本来需要编写的Java代码量。

然而,在我的一个Java类中,我不确定如何在Kotlin中实现相同的结果。

我的Java类看起来有点像这样:

public class DataObject {

    private int mId;
    private String mName;

    public DataObject(int id, String name) {
        mId = id;
        mName = name;
    }

    public DataObject(Context context, int id) {
        mId = id;
        Cursor cursor = ...
        cursor.moveToFirst();
        mName = cursor.getString(...);
        cursor.close();
    }

    public int getId() {
        return mId;
    }

    public String getName() {
        return mName;
    }

}

我尝试用Kotlin重写它,目前为止我有这个:

data class DataObject(val id: Int, val name: String) {

    constructor(context: Context, id: Int) : this(id, fetchName(context))

    private fun fetchName(context: Context): String {
        val cursor = ...
        cursor.moveToFirst()
        val name = cursor.getString(...)
        cursor.close()
        return name
    }

}

但是我的IDE(Android Studio)在我的构造函数中调用fetchName(context)的部分被用红色下划线标出。它显示以下消息:

在调用超类构造函数之前无法访问fetchName

我应该如何解决这个问题?


请注意,这里实际上不需要 data - voddan
@voddan,“data”指的是“数据类”吗?为什么不呢? - Farbod Salamat-Zadeh
你的初始Java类没有toStringequals,对吧?所以如果你添加了data,Kotlin版本实际上会做更多的事情。这并不是什么坏事,但需要注意一下 ;) - voddan
2个回答

19

只有完全构造的对象才能使用成员函数。解决这个问题的一种方法是使用私有扩展函数或者简单地使用一个函数来获取名称:

private fun Context.fetchName(): String {
    ///...
    return cursor.getString(1)
}

data class DataObject(val id: Int, val name: String) {
    constructor(context: Context, id: Int) : this(id, context.fetchName())
}

虽然我认为在constructor中使用Cursor有些过于繁重, 我会使用单独的工厂来实现:

data class DataObject(val id: Int, val name: String) {
    object FromCursorFactory {
        fun create(id: Int, context: Context): DataObject {
            val name = context.fetchName()
            return DataObject(id, name)
        }
    }
}

更多阅读:


谢谢。我有一个小问题。当我将扩展函数Context.fetchName()放在数据类中时,它仍然给了我警告,但是当我将其移到数据类外部时,警告消失了。为什么会这样? - Farbod Salamat-Zadeh
3
当扩展函数位于类中时,它仍然是一个具有访问封闭类实例的所有成员的函数,因此需要引用该实例。 - miensol

3
另一种方法是使用伴生对象。这将允许您在数据类外部调用该函数(在您特定的情况下可能没有用处)。
data class DataObject(val id: Int, val name: String) {

  constructor(context: Context, id: Int) : this(id, fetchName(context))

  companion object {

    fun fetchName(context: Context): String {
      val cursor = ...
      ...
      return name
    }
  }
}

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