我想生成一个随机数以存储在case类的“ id”成员中,并在存储在数据库中时用作主键。如果传递的id值非零,则应使用该值,而不要生成新的值。
case class User(name: String, id: Long = 0L)
我尝试过
object User {
def apply(name: String, id: Long): User =
User(name, (id == 0L) ? <some random number> : id)
}
但是会出现一些错误,例如:
ambiguous reference to overloaded definition
...
method apply is defined twice
我不想在案例类中引入其他成员。
答案 0 :(得分:4)
作为错误消息的统计信息,您将覆盖您的apply方法。您应该在new
定义中使用apply
。
object User {
def apply(name: String, id: Long): User =
new User(name, if(id == 0L) <some random number> else id)
}
答案 1 :(得分:1)
此处不支持?:
三元运算符。错误apply method defined twice
被定义为case class
。但是即使在case class
的定义中,它也已在scala 2.12.6中成功编译。我改成这个,然后编译:
class User(name: String, id: Long = 0L)
object User {
def apply(name: String, id: Long): User =
new User(name,if(id == 0L) scala.util.Random.nextLong else id)
}
scala> :paste
// Entering paste mode (ctrl-D to finish)
class User(name: String, id: Long = 0L)
object User {
def apply(name: String, id: Long): User =
new User(name,if(id == 0L) scala.util.Random.nextLong else id)}
// Exiting paste mode, now interpreting.
defined class User
defined object User
scala>
答案 2 :(得分:1)
其他人指出,scala使用if ... else
而不是Java的? .. : ..
(在解决了“应用两次定义”问题之后,您将收到此错误)。
直接的问题是,案例类具有为它们生成的默认apply
方法,带有案例类的参数,因此您要定义的是重复的。
您可以通过以下方法解决此问题:从构造函数中删除默认值,然后从apply中删除第二个参数:
case class User(name: String, id: Long)
object User { def apply(name: String) = User(name, Random.nextLong) }
这将进行编译,而且效果更好,因为您不再需要将0视为前哨值。当您执行User(name, 1)
时,将调用默认的apply,并获得具有给定ID的实例,当您执行User(name)
时,它将调用自定义apply
,并获得一个随机ID ,
我想,您知道在这种简单情况下,您可以做
case class User(name: String, id: Long = Random.nextLong)
,对吧?当一个(或多个)参数的默认值取决于其他参数的值时,这种方法(带有重载)更有用,这样您就不能只在参数列表中写入默认值,例如:< / p>
case class Parent(child: Person, lastName: String)
object Parent {
def apply(child: Person) = Parent(child, child.lastName)
}
答案 3 :(得分:0)
我通常的做法是这样的
case class User(name: String, private val _id: Long = 0L) {
lazy val id: Long = if(_id == 0) Random.nextLong() else _id
}
编辑:请注意,这种方法在案例类上有违反平等合同的缺点:您通过_id = 0
传递的2个User实例将具有不同的ID,但相等,因为case类的equals方法仅查看构造函数的参数