Scala - 使用复杂的泛型获取 subclass 和另一个 class 的信息 - 无法编译?

Scala - Using complicated generics to get information of a subclass and another class - doesn't compile?

我正在用 scala 编写一个程序,该程序使用以下框架:

trait Tool[T <: Tool[T, U], U <: Settings[T]] {
  // members here
  def createSettingsFrom(settingsWithStringNames: Map[String, _]): U
}

trait Settings[T <: Tool[T, _ <: Settings[T]]

在Tool中,T是子class,U是class,为它携带信息。每个工具都可以看作是一种带有参数的命令,这些参数是为每个工具自定义的。

我还有一个扩展它的 class,以及它的 "information carrier":

object Cleanup extends Tool[Cleanup, CleanupSettings] {
  override def createSettingsFrom(settings: Map[String, _]): CleanupSettings 
    = CleanupSettings(
      settings.get("attribute1").asInstanceOf[Int]
      settings.get("attribute2").asInstanceOf[String])
}

case class CleanupSettings extends Settings[Cleanup](
  //attribute1: Int,
  //attribute2: String
  //more attributes)

当我尝试编译这些 classes 时,我得到以下堆栈跟踪:

Information:21/10/16 03:20 - Compilation completed with 2 errors and 0 warnings in 3s 200ms /project_folder/src/main/scala/io/oreville/maptools/operations/cleanup/Cleanup.scala Error:(17, 24) type arguments [package.tools.operations.cleanup.Cleanup,package.tools.operations.cleanup.CleanupSettings] do not conform to trait ConfigurableTool's type parameter bounds [T <: package.tools.ConfigurableTool[T,U],U <: package.tools.params.Settings[T]] object Cleanup extends ConfigurableTool[Cleanup, CleanupSettings] { ^ /project_folder/src/main/scala/io/oreville/maptools/operations/cleanup/CleanupSettings.scala Error:(11, 11) type arguments [package.tools.operations.cleanup.Cleanup] do not conform to trait Settings's type parameter bounds [T <: package.tools.Tool[T, _ <: package.tools.params.Settings[T]]] extends Settings[Cleanup] ^

我还有一个特征 ConfigurableTool,它只是 Tool 的扩展,具有一些额外的功能,因此它具有完全相同的通用签名,只是 extends Tool[T, U].

我尝试了多种方法来解决这个问题,包括将 + 和 - 的组合添加到我的泛型中以实现协变和逆变,但没有帮助。 我确实考虑过为我的设置使用动态类型,但速度是一个因素。我什至不知道这样做是否能解决问题。

就是这样,我希望你有时间来帮助我,如果没有,还是感谢阅读!

我无法重现您收到的错误消息。

代码中有一些拼写错误,但在清理它们之后,唯一剩下的错误是 Cleanup 的定义,在扩展特征时不能将其作为类型参数传递。

object Cleanup extends Tool[Cleanup.type, CleanupSettings] { ... }

illegal cyclic reference involving object Cleanup

您可以通过将其作为特征并在伴随对象中扩展它来解决这个问题。这是完整的代码:

trait Tool[T <: Tool[T, U], U <: Settings[T]] {
  // members here
  def createSettingsFrom(settingsWithStringNames: Map[String, _]): U
}

trait Settings[T <: Tool[T, _ <: Settings[T]]]

trait Cleanup extends Tool[Cleanup, CleanupSettings] {
  override def createSettingsFrom(settings: Map[String, _]): CleanupSettings = CleanupSettings(
    settings.get("attribute1").asInstanceOf[Int],
    settings.get("attribute2").asInstanceOf[String])
}
object Cleanup extends Cleanup

case class CleanupSettings(
  attribute1: Int,
  attribute2: String) extends Settings[Cleanup]