Scala 重载'apply'方法时:滑动错误消息';值元组不是对象';

Scala 重载'apply'方法时:滑动错误消息';值元组不是对象';,scala,slick,Scala,Slick,在某些情况下,我需要能够通过提供除id之外的所有值来创建User对象,以便User对象负责为自己分配自动生成的值 为此,我在伴生对象中重载了apply方法,如下所示。但这会导致编译时错误:值tuple不是对象的成员 StackOverflow和其他博客上提到的解决方案不起作用,例如: case类用户(id:Long,firstName:String,lastName:String,mobile:Long,email:String) 对象用户{ private val seq=新原子长度 def

在某些情况下,我需要能够通过提供除
id
之外的所有值来创建
User
对象,以便
User
对象负责为自己分配自动生成的值

为此,我在伴生对象中重载了apply方法,如下所示。但这会导致编译时错误:
值tuple不是对象的成员

StackOverflow和其他博客上提到的解决方案不起作用,例如:

case类用户(id:Long,firstName:String,lastName:String,mobile:Long,email:String)
对象用户{
private val seq=新原子长度
def apply(firstName:String,lastName:String,mobile:Long,email:String):用户={
用户(seq.incrementAndGet()、姓氏、姓氏、手机、电子邮件)
}
}
类UserTableDef(tag:tag)扩展表[User](tag,“User”){
def id=列[Long](“id”,O.PrimaryKey,O.AutoInc)
def firstName=列[字符串](“名字”)
def lastName=列[字符串](“姓氏”)
def mobile=列[长](“移动”)
def email=列[字符串](“电子邮件”)
超控def*=
(id、firstName、lastName、mobile、email)(User.tuple、User.unapply)
}
注意:使用内部原子长度作为
id生成器,而不是使用自动增量序列生成器 数据库提供,因为它们可以安全地防止来自 多个应用程序

现在回到代码,在函数上定义了tuple方法,并将具有N个参数的函数转换为具有单个参数的函数,一个N元元组

从您的描述来看,重载apply方法似乎会导致编译器无法确定应该选择哪个“apply”实现。因此,您可能应该做两件事:

  • 重命名第二个应用程序(通常,请避免重载)
  • 显式调用tuple(即User.withEmptyId.tuple)

  • 一种可能的解决方案是将
    二级构造函数
    推送到
    案例类
    定义本身,然后使用问题中指定的博客文章中提到的解决方法

    然后,您可以创建
    User
    对象,而无需指定
    id
    ,但是,您可能仍然需要使用
    new
    关键字,如so
    newuser(firstName、lastName、mobile、email)

    case类用户(id:Long,firstName:String,lastName:String,mobile:Long,email:String){
    定义此(名字:String,名字:String,手机:Long,电子邮件:String)=
    这(User.seq.incrementAndGet()、firstName、lastName、mobile、email)
    }
    对象用户{
    private val seq=新原子长度
    }
    类UserTableDef(tag:tag)扩展表[User](tag,“User”){
    def id=列[Long](“id”,O.PrimaryKey,O.AutoInc)
    def firstName=列[字符串](“名字”)
    def lastName=列[字符串](“姓氏”)
    def mobile=列[长](“移动”)
    def email=列[字符串](“电子邮件”)
    超控def*=
    (id,firstName,lastName,mobile,email)((User.apply..tuple,User.unapply)
    }
    
    问题的根源在于过载的
    apply
    def

    元组
    不适用于
    案例类
    参数少于2个
    重载应用

    就slick的
    *
    (或所有)映射和
    而言,它应该是这样的

    def * = (tupleMember1, tupleMember2, ...) <> (func1, func2)
    

    编译器不会自动为case类中的二级构造函数生成
    apply
    方法。然而,我们可以重载
    人。在同伴对象中应用
    ,我们可以拥有方便的“构造函数”,并避免使用
    的要求。Dean Wampler用Scala编程。请你详细说明你在这方面的陈述“一般来说,请避免超载”好吗?重命名apply方法在这里不起作用,对吗?“数据库提供的自动增量序列生成器”:::您还可以解释一下如何在Slick中实现这一点吗?也许你能给我指一些链接?非常感谢!一般来说,重载可能会导致类型推断的case问题,因为每个方法都是一个函数。请看以下语句:val a=User.apply。编译器怎么知道我们在讨论哪个应用程序?我刚刚将
    id:Long
    更改为
    id:Option[Long]
    ,并创建了
    User
    ,就像
    这样(无、名、姓、手机、电子邮件)
    通过将
    None
    作为
    id
    传递,Slick负责为
    id
    提供一个自动递增的值。谢谢!避免使用像应用程序代码这样的长id代码。您可以通过将
    id
    设置为
    Option[Long]
    将其留给数据库来管理,也可以使用UUID之类的工具。谢谢。这个很好用。但我在声明隐式序列化程序
    implicit val userReads=Json时遇到了一个后续问题。reads[User]
    :对重载定义的引用不明确,这两种方法都适用于类型(id:Option[Long],firstName:String,lastName:String,mobile:Long,email:String)的对象用户模型。用户和方法应用于类型为(firstName:String,lastName:String,mobile:Long,email:String)模型的对象用户。用户匹配预期类型?是。。。这将在Play Json的reader宏中发生。您可以编写自己的读取实现。以下解决方案解决了序列化程序问题:
    mapperTo
    方法的正确签名将是:
    def mapperTo(id:Long,firstName:String,lastName:String,mobile:Long,email:String)=apply(id,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)
    
    }
    
    def * = (tupleMember1, tupleMember2, ...) <> (func1, func2)
    
    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)
    
    }