重载 `apply` 方法时:光滑的错误消息 'value tupled is not a member of object'
When overloading `apply` method: Slick error message 'value tupled is not a member of object'
我需要能够通过在某些情况下提供除 id
之外的所有值来创建 User
对象,这样 User
对象负责为自己分配一个自动-产生的价值。
为此,我重载了伴随对象中的 apply 方法,如下所示。但这会导致编译时错误:value tupled is not a member of object
.
Whosebug 和其他博客中提及的解决方案均无效,例如:
http://queirozf.com/entries/slick-error-message-value-tupled-is-not-a-member-of-object
case class User(id: Long, firstName: String, lastName: String, mobile: Long, email: String)
object User {
private val seq = new AtomicLong
def apply(firstName: String, lastName: String, mobile: Long, email: String): User = {
User(seq.incrementAndGet(), firstName, lastName, mobile, email)
}
}
class UserTableDef(tag: Tag) extends Table[User](tag, "user") {
def id = column[Long]("id", O.PrimaryKey, O.AutoInc)
def firstName = column[String]("first_name")
def lastName = column[String]("last_name")
def mobile = column[Long]("mobile")
def email = column[String]("email")
override def * =
(id, firstName, lastName, mobile, email) <> (User.tupled, User.unapply)
}
Notice: It is probably a bad idea to use an internal atomic long as an
id generator instead of using auto-increment sequence generator that
database provide, as these are safe against concurrent access from
multiple applications.
现在回到代码,tupled 方法定义在函数上,并将具有 N 个参数的函数 转换为函数使用 单个 参数,N 元元组
根据您的描述,似乎重载 apply 方法会导致编译器无法确定应选择哪个 "apply" 实现。因此,您可能应该做两件事:
- 重命名第二个应用程序(一般情况下,请避免重载)
- 明确调用元组(即User.withEmptyId.tupled)
一种可能的解决方案是将 secondary constructor
推送到 case class
定义本身,然后使用问题中指定的博客 post 中提到的解决方法。
然后您可以在不指定 id
的情况下创建 User
对象,但是,您可能仍需要使用 new
关键字,例如 new User(firstName, lastName, mobile, email)
.
case class User(id: Long, firstName: String, lastName: String, mobile: Long, email: String) {
def this(firstName: String, lastName: String, mobile: Long, email: String) =
this(User.seq.incrementAndGet(), firstName, lastName, mobile, email)
}
object User {
private val seq = new AtomicLong
}
class UserTableDef(tag: Tag) extends Table[User](tag, "user") {
def id = column[Long]("id", O.PrimaryKey, O.AutoInc)
def firstName = column[String]("first_name")
def lastName = column[String]("last_name")
def mobile = column[Long]("mobile")
def email = column[String]("email")
override def * =
(id, firstName, lastName, mobile, email) <> ((User.apply _).tupled, User.unapply)
}
你的问题的根源是 apply
def.
过载
tupled
不适用于 case class
和 less than 2 parameters
或 overloaded apply
。
就 slick 的 *
(或全部)映射和 <>
而言,它应该是这样的,
def * = (tupleMember1, tupleMember2, ...) <> (func1, func2)
这样,
func1
将元组 (tupleMember1, tupleMember2, ...)
作为输入,returns 是映射 class/case class. 的一个实例
func1
获取映射 class/case class 和 returns 元组 (tupleMember1, tupleMember2, ...)
. 的实例
因此您可以提供满足这些要求的任何功能...
case class User(id: Long, firstName: String, lastName: String, mobile: Long, email: String)
object User {
private val seq = new AtomicLong
def apply(firstName: String, lastName: String, mobile: Long, email: String): User = {
User(seq.incrementAndGet(), firstName, lastName, mobile, email)
}
def mapperTo(
id: Long, firstName: String,
lastName: String, mobile: Long, email: String
) = apply(id, firstName, lastName, mobile, email)
}
class UserTableDef(tag: Tag) extends Table[User](tag, "user") {
def id = column[Long]("id", O.PrimaryKey, O.AutoInc)
def firstName = column[String]("first_name")
def lastName = column[String]("last_name")
def mobile = column[Long]("mobile")
def email = column[String]("email")
override def * =
(id, firstName, lastName, mobile, email) <> ((User.mapperTo _).tupled, User.unapply)
}
我需要能够通过在某些情况下提供除 id
之外的所有值来创建 User
对象,这样 User
对象负责为自己分配一个自动-产生的价值。
为此,我重载了伴随对象中的 apply 方法,如下所示。但这会导致编译时错误:value tupled is not a member of object
.
Whosebug 和其他博客中提及的解决方案均无效,例如: http://queirozf.com/entries/slick-error-message-value-tupled-is-not-a-member-of-object
case class User(id: Long, firstName: String, lastName: String, mobile: Long, email: String)
object User {
private val seq = new AtomicLong
def apply(firstName: String, lastName: String, mobile: Long, email: String): User = {
User(seq.incrementAndGet(), firstName, lastName, mobile, email)
}
}
class UserTableDef(tag: Tag) extends Table[User](tag, "user") {
def id = column[Long]("id", O.PrimaryKey, O.AutoInc)
def firstName = column[String]("first_name")
def lastName = column[String]("last_name")
def mobile = column[Long]("mobile")
def email = column[String]("email")
override def * =
(id, firstName, lastName, mobile, email) <> (User.tupled, User.unapply)
}
Notice: It is probably a bad idea to use an internal atomic long as an id generator instead of using auto-increment sequence generator that database provide, as these are safe against concurrent access from multiple applications.
现在回到代码,tupled 方法定义在函数上,并将具有 N 个参数的函数 转换为函数使用 单个 参数,N 元元组
根据您的描述,似乎重载 apply 方法会导致编译器无法确定应选择哪个 "apply" 实现。因此,您可能应该做两件事:
- 重命名第二个应用程序(一般情况下,请避免重载)
- 明确调用元组(即User.withEmptyId.tupled)
一种可能的解决方案是将 secondary constructor
推送到 case class
定义本身,然后使用问题中指定的博客 post 中提到的解决方法。
然后您可以在不指定 id
的情况下创建 User
对象,但是,您可能仍需要使用 new
关键字,例如 new User(firstName, lastName, mobile, email)
.
case class User(id: Long, firstName: String, lastName: String, mobile: Long, email: String) {
def this(firstName: String, lastName: String, mobile: Long, email: String) =
this(User.seq.incrementAndGet(), firstName, lastName, mobile, email)
}
object User {
private val seq = new AtomicLong
}
class UserTableDef(tag: Tag) extends Table[User](tag, "user") {
def id = column[Long]("id", O.PrimaryKey, O.AutoInc)
def firstName = column[String]("first_name")
def lastName = column[String]("last_name")
def mobile = column[Long]("mobile")
def email = column[String]("email")
override def * =
(id, firstName, lastName, mobile, email) <> ((User.apply _).tupled, User.unapply)
}
你的问题的根源是 apply
def.
tupled
不适用于 case class
和 less than 2 parameters
或 overloaded apply
。
就 slick 的 *
(或全部)映射和 <>
而言,它应该是这样的,
def * = (tupleMember1, tupleMember2, ...) <> (func1, func2)
这样,
func1
将元组(tupleMember1, tupleMember2, ...)
作为输入,returns 是映射 class/case class. 的一个实例
func1
获取映射 class/case class 和 returns 元组(tupleMember1, tupleMember2, ...)
. 的实例
因此您可以提供满足这些要求的任何功能...
case class User(id: Long, firstName: String, lastName: String, mobile: Long, email: String)
object User {
private val seq = new AtomicLong
def apply(firstName: String, lastName: String, mobile: Long, email: String): User = {
User(seq.incrementAndGet(), firstName, lastName, mobile, email)
}
def mapperTo(
id: Long, firstName: String,
lastName: String, mobile: Long, email: String
) = apply(id, firstName, lastName, mobile, email)
}
class UserTableDef(tag: Tag) extends Table[User](tag, "user") {
def id = column[Long]("id", O.PrimaryKey, O.AutoInc)
def firstName = column[String]("first_name")
def lastName = column[String]("last_name")
def mobile = column[Long]("mobile")
def email = column[String]("email")
override def * =
(id, firstName, lastName, mobile, email) <> ((User.mapperTo _).tupled, User.unapply)
}