Kotlin - 为可空字段创建非空的getter方法

10

我刚接触 Kotlin,想用这门新语言改写一个小的 Java 项目。我的项目中使用了 MongoDB 数据库,并有一个类如下:

class PlayerEntity {

  constructor() {} //for mongodb to create an instance

  constructor(id: ObjectId, name: String) { //used in code
    this.id = id
    this.name = name
  }

  @org.mongodb.morphia.annotations.Id
  var id: ObjectId? = null

  var name: String? = null
}

由于空构造函数的缘故,我不得不将id字段标记为可为空(var id: ObjectId?)。当我尝试从另一个类中访问此字段时,我必须使用非空检查:thePlayer.id!!。但是我的应用程序逻辑是id字段永远不会为空 (mongo在创建Player实例并立即设置id字段后)。而我不想在每个地方都进行非空检查。

我尝试创建一个非空的getter,但它无法编译:

var id: ObjectId? = null
    get(): ObjectId = id!!

我也可以为id创建一些存根并在构造函数中使用它,但这看起来像是一个肮脏的hack:

val DUMMY_ID = new ObjectId("000000000000000000000000");

那么有没有解决这个问题的变通方法?


2
在你的变量前加上 lateinit,它基本上意味着不用担心如何初始化,我会确保它被初始化。 - succcubbus
这个类似的Hibernate问题和解决方案是否有帮助? - miensol
1个回答

4

在类似的情况下,我个人使用以_为前缀的私有变量 + 公共val。

class Example<out T> {
  private var _id: T? = null
  val id: T
    get() = _id!!
}

对于您的情况,应该是这样的:

@org.mongodb.morphia.annotations.Id
private var _id: ObjectId? = null
val id: ObjectId
  get() = _id!!

或者,你可以像这样声明变量为lateinit(但请注意,这会公开暴露setter):

@org.mongodb.morphia.annotations.Id
lateinit var id: ObjectId

4
在这种情况下,使用lateinit是正确的做法;不需要费心去用第二个属性。 - yole
谢谢,lateinit 就是我需要的。 - awfun
2
@yole 每个人都有自己的喜好,但出于某种原因,我个人不太喜欢使用 lateinit - F. George
在类似的情况下,我个人使用以_为前缀的私有变量 + 公共val。这与具有私有setter的公共var有什么区别?有吗? - Rocoty
3
一个getter/setter无法覆盖其父级变量的类型,因此任何使用getter的人仍然需要非空断言(!!)返回值。 - F. George

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