Scala 如何复制case类并添加mixin?

Scala 如何复制case类并添加mixin?,scala,case-class,Scala,Case Class,我想有一个基本的案例类,我可以扩展到不同的类型随意。我以前做过类似的工作,但我一定把事情搞砸了,因为现在我遇到了编译错误 trait JobLike case class Task(name: String) { def as[T <: JobLike]: Task with T = new Task(this.name) with T } 我发誓,我昨天做了一些工作,基本上就是这样做的,但现在它抛出了这个错误。你成功地碰到了一个编译器错误!虽然这确实是一个问题,应该报告,但问

我想有一个基本的案例类,我可以扩展到不同的类型随意。我以前做过类似的工作,但我一定把事情搞砸了,因为现在我遇到了编译错误

trait JobLike

case class Task(name: String) {

  def as[T <: JobLike]: Task with T = new Task(this.name) with T

}

我发誓,我昨天做了一些工作,基本上就是这样做的,但现在它抛出了这个错误。

你成功地碰到了一个编译器错误!虽然这确实是一个问题,应该报告,但问题是你的代码无论如何都不可能实现,它崩溃并把你带到这里比“工作”和做一些可怕的错误要好。因为
T
可以是
JobLike
的任何子类型,所以根本无法在编译时将其混合在一起。我可以很好地做
trait,比如{def something:Int};task.as[Boom]
,然后
task
无法创建
Boom
,因为没有
某物的实现

您可以使用JobLike
提供
asJobLike:Task,而不是将常规的
as[T]:Task设置为T
,这是完全可能的。(请注意,不鼓励创建
案例类
的子类型,因此您可能希望创建一个新类。原因是它会破坏
等于
的自反性)

你可以做的一件相当肮脏的事情就是调用
(新任务(this.name)和JobLike.asInstanceOf[Task with T]
asInstanceOf
仅检查
中最左边类型的强制转换,因此这不会立即执行
ClassCastException
(您也可以执行
“a”。asInstanceOf[String with Int]
)。只要
T
没有成员,它通常会分类工作(模数
作为[T]
的实例
false


您还可以使用运行时反射动态创建所需的类。这个技巧整体上是肮脏的,完全不安全的,所以我在这里不说,但是有一个问题。

你设法碰到了一个编译器错误!虽然这确实是一个问题,应该报告,但问题是你的代码无论如何都不可能实现,它崩溃并把你带到这里比“工作”和做一些可怕的错误要好。因为
T
可以是
JobLike
的任何子类型,所以根本无法在编译时将其混合在一起。我可以很好地做
trait,比如{def something:Int};task.as[Boom]
,然后
task
无法创建
Boom
,因为没有
某物的实现

您可以使用JobLike
提供
asJobLike:Task,而不是将常规的
as[T]:Task设置为T
,这是完全可能的。(请注意,不鼓励创建
案例类
的子类型,因此您可能希望创建一个新类。原因是它会破坏
等于
的自反性)

你可以做的一件相当肮脏的事情就是调用
(新任务(this.name)和JobLike.asInstanceOf[Task with T]
asInstanceOf
仅检查
中最左边类型的强制转换,因此这不会立即执行
ClassCastException
(您也可以执行
“a”。asInstanceOf[String with Int]
)。只要
T
没有成员,它通常会分类工作(模数
作为[T]
的实例
false


您还可以使用运行时反射动态创建所需的类。技巧作为一个整体是肮脏和完全不安全的,所以我在这里不说,但有一个。

我找不到一个编译器版本,它可以成功编译,但通常它会失败,因为
t不是类类型
,所以这看起来像是一种回归。考虑提交一个bug报告,因为我找不到编译器版本,这个版本编译成功了,但通常应该失败。<代码> T不是类类型< /C> >,所以这看起来是一种回归。考虑提交bug报告
java.lang.UnsupportedOperationException: addChild inapplicable for type T
at scala.reflect.internal.Symbols$Symbol.addChild(Symbols.scala:1835)
at scala.tools.nsc.typechecker.Namers$Namer.$anonfun$templateSig$1(Namers.scala:1119)
at scala.tools.nsc.typechecker.Namers$Namer.templateSig(Namers.scala:1107)
at scala.tools.nsc.typechecker.Namers$Namer.classSig(Namers.scala:1178)
at scala.tools.nsc.typechecker.Namers$Namer.memberSig(Namers.scala:1788)
at scala.tools.nsc.typechecker.Namers$Namer.typeSig(Namers.scala:1751)
at scala.tools.nsc.typechecker.Namers$Namer$MonoTypeCompleter.completeImpl(Namers.scala:836)
...
at scala.tools.nsc.MainGenericRunner.runTarget$1(MainGenericRunner.scala:82)
at scala.tools.nsc.MainGenericRunner.run$1(MainGenericRunner.scala:85)
at scala.tools.nsc.MainGenericRunner.process(MainGenericRunner.scala:96)
at scala.tools.nsc.MainGenericRunner$.main(MainGenericRunner.scala:101)
at scala.tools.nsc.MainGenericRunner.main(MainGenericRunner.scala)</code>