2016-10-21 5 views
0

Я пишу программу в Скале, которая использует рамки вокруг: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]] 

инструмента, T является подклассом, и U является классом, который несет в себе информацию для него. Каждый Инструмент можно рассматривать как своего рода команду с параметрами, и эти параметры являются обычными для каждого из них.

У меня также есть класс, который расширяет его вместе с его «носитель информации»:

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) 

При попытке скомпилировать эти классы, я получаю следующую трассировку стека:

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, которое является просто расширением инструмента с некоторой дополнительной функциональностью, поэтому оно имеет ту же общую подпись, и только extends Tool[T, U].

Я попробовал несколько вещей, чтобы решить проблему, включая добавление комбинаций + и - к моим дженерикам для совместной и контравариантности, но это не помогает. Я действительно рассматривал использование динамического типа для моих настроек, но скорость - это немного фактор. Я даже не знаю, решит ли это проблему, если я это сделаю.

Вот и все, я надеюсь, что у вас есть время, чтобы помочь моему делу, если нет, спасибо за чтение в любом случае!

ответ

0

Я не смогу воспроизвести сообщение об ошибке, которое вы получили.

В коде есть несколько опечаток, но после их очистки единственная ошибка в этом случае указана в определении Cleanup, которое вы не можете передать как параметр типа при расширении черты.

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

нелегальная циклическая ссылка с участием объекта 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] 
+0

О, это очень здорово. В результате я удалил параметр типа подкласса, чтобы упростить его. Я понял, что ссылка на «Очистка» - это не то же самое, что ссылаться на его класс, но это хороший обходной путь для циклической ссылки. Спасибо :) – Dico

 Смежные вопросы

  • Нет связанных вопросов^_^