依赖于特征中案例类的方法

发布于 2024-10-23 14:52:49 字数 519 浏览 8 评论 0原文

有没有办法依赖特征中案例类中定义的方法?例如,复制:以下内容不起作用。但我不确定为什么。

trait K[T <: K[T]] {
  val x: String
  val y: String
  def m: T = copy(x = "hello")
  def copy(x: String = this.x, y: String = this.y): T
}

case class L(val x: String, val y: String) extends K[L]

给出:

error: class L needs to be abstract, since method copy in trait K of type 
(x: String,y: String)L is not defined
           case class L(val x: String, val y: String) extends K[L]
                      ^

Is there a way to rely on methods defined in case class in a trait? E.g., copy: the following doesn't work. I'm not sure why, though.

trait K[T <: K[T]] {
  val x: String
  val y: String
  def m: T = copy(x = "hello")
  def copy(x: String = this.x, y: String = this.y): T
}

case class L(val x: String, val y: String) extends K[L]

Gives:

error: class L needs to be abstract, since method copy in trait K of type 
(x: String,y: String)L is not defined
           case class L(val x: String, val y: String) extends K[L]
                      ^

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

紫罗兰の梦幻 2024-10-30 14:52:49

解决方案是声明您的特征必须应用于具有复制方法的类:(

trait K[T <: K[T]] {this: {def copy(x: String, y: String): T} =>
  val x: String
  val y: String
  def m: T = copy(x = "hello", y)
}

不幸的是,您不能在复制方法中使用隐式参数,因为类型声明中不允许隐式声明)

那么您的声明就可以了

case class L(val x: String, val y: String) extends K[L]

:(在 REPL scala 2.8.1 中进行了测试)

您的尝试不起作用的原因在其他用户提出的解决方案中进行了解释:您的 copy 声明阻止了“case copy”方法。

A solution is to declare that your trait must be applied to a class with a copy method:

trait K[T <: K[T]] {this: {def copy(x: String, y: String): T} =>
  val x: String
  val y: String
  def m: T = copy(x = "hello", y)
}

(unfortunately you can not use implicit parameter in the copy method, as implicit declaration is not allowed in the type declaration)

Then your declaration is ok:

case class L(val x: String, val y: String) extends K[L]

(tested in REPL scala 2.8.1)

The reason why your attempt does not work is explained in the solution proposed by other users: your copy declaration block the generation of the "case copy" method.

怪我入戏太深 2024-10-30 14:52:49

我认为在特征中使用名称为 copy 的方法会指示编译器不在案例类中生成方法副本 - 因此在您的示例中,方法副本未在您的案例类中实现。下面是在特征中实现方法复制的简短实验:

scala> trait K[T <: K[T]] {                                                                                   
     | val x: String                                                                                          
     | val y: String                                                                                          
     | def m: T = copy(x = "hello")                                                                           
     | def copy(x: String = this.x, y: String = this.y): T = {println("I'm from trait"); null.asInstanceOf[T]}
     | }

defined trait K

scala> case class L(val x: String, val y: String) extends K[L]                                                
defined class L

scala> val c = L("x","y")                                                                                     
c: L = L(x,y)

scala> val d = c.copy()                                                                                       
I'm from trait
d: L = null

I suppose that having method with name copy in trait instructs compiler to not generate method copy in case class - so in your example method copy is not implemented in your case class. Below short experiment with method copy implemented in trait:

scala> trait K[T <: K[T]] {                                                                                   
     | val x: String                                                                                          
     | val y: String                                                                                          
     | def m: T = copy(x = "hello")                                                                           
     | def copy(x: String = this.x, y: String = this.y): T = {println("I'm from trait"); null.asInstanceOf[T]}
     | }

defined trait K

scala> case class L(val x: String, val y: String) extends K[L]                                                
defined class L

scala> val c = L("x","y")                                                                                     
c: L = L(x,y)

scala> val d = c.copy()                                                                                       
I'm from trait
d: L = null
月野兔 2024-10-30 14:52:49

您可以使用 $scala -Xprint:typer 运行 repl。使用参数 -Xprint:typer 您可以看到创建特征或类时到底发生了什么。并且您将从输出中看到该方法“copy”未创建,因此编译器要求您自己定义它。

You can run repl with $scala -Xprint:typer. With parameter -Xprint:typer you can see what exactly happening when you create trait or class. And you will see from output that method "copy" not created, so compiler requests to define it by yourself.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文