【问题标题】:Scala generic type parameters issuesScala泛型类型参数问题
【发布时间】:2017-08-31 21:33:52
【问题描述】:

我对 Scala 比较陌生,并且遇到了泛型类型参数的问题。我正在为某些操作实现命令模式,并且我有一个这样的基类:

abstract class Command[A, B <: BaseModel, T[X] <: CommandResponseWrapper[X] forSome { type X }](repository: BaseRepository[A, B], entity: B) {

  @throws(classOf[Exception])
  def execute: Future[T[X] forSome { type X }]
}

现在,将这个具体命令作为我遇到的问题的一个示例:

case class AgentExecutionListCommand(repository: AgentExecutionRepository[Int, AgentExecution], entity: AgentExecution)(implicit ec: ExecutionContext) extends Command[Int, AgentExecution, AgentExecutionListResponse[Seq[AgentExecution]]](repository, entity){
  override def execute: Future[AgentExecutionListResponse[Seq[AgentExecution]]] = {
    repository.getAllMastersForAgent(entity.agentId).map(ae => AgentExecutionListResponse(ae))
  }

  override def toString: String = "Command is: AgentExecutionListCommand"
}

case class AgentExecutionListResponse[Seq[AgentExecution]](response: Seq[AgentExecution]) extends CommandResponseWrapper

存储库中的方法getAllMastersForAgent,返回一个Future[Seq[AgentExecution]],但是编译器在这一行显示错误:

repository.getAllMastersForAgent(entity.agentId).map(ae => AgentExecutionListResponse(ae))

错误是:AgentExecutionListResponse[Seq] 类型的表达式不符合预期的类型 S_

这是什么意思?

另一个错误是:

Error:(11, 189) org.jc.dpwmanager.commands.AgentExecutionListResponse[Seq[org.jc.dpwmanager.models.AgentExecution]] takes no type parameters, expected: one
case class AgentExecutionListCommand(repository: AgentExecutionRepository[Int, AgentExecution], entity: AgentExecution)(implicit ec: ExecutionContext) extends Command[Int, AgentExecution, AgentExecutionListResponse[Seq]](repository, entity){

为什么它说它不接受类型参数,然后又需要一个。我不明白。请帮忙!

提前致谢!

【问题讨论】:

    标签: scala generics


    【解决方案1】:

    问题出在这里:

     case class AgentExecutionListResponse[Seq[AgentExecution]](response: Seq[AgentExecution]) extends CommandResponseWrapper
    

    [...] 应该在CommandResponseWrapper 之后而不是在类名之后

      case class AgentExecutionListResponse(
        response: Seq[AgentExecution]
      ) extends CommandResponseWrapper[Seq[AgentExecution]]
    

    【讨论】:

      【解决方案2】:

      对于第二个错误:

      T[X] &lt;: CommandResponseWrapper[X] forSome { type X } 表示您告诉编译器 T 必须是具有单个参数的类型构造函数(这就是为什么您可以在 execute 的签名中写 T[X]),但 AgentExecutionListResponse[Seq[AgentExecution]] 不接受参数(你不能写AgentExecutionListResponse[Seq[AgentExecution]][SomeType])。所以你不能将它用作T。就像您尝试调用 foo() 一样,其中 foo 有一个参数。

      另外,我认为XforSome中的作用域只是CommandResponseWrapper[X] forSome { type X },所以和T[X] &lt;: CommandResponseWrapper[_]是一样的。所以在T[X] 中命名X 会让人困惑。

      鉴于您期望 AgentExecutionListCommand#execute 的签名,修复可能只是

      abstract class Command[A, B <: BaseModel, T <: CommandResponseWrapper[_]](repository: BaseRepository[A, B], entity: B) {
      
        @throws(classOf[Exception])
        def execute: Future[T]
      }
      

      但这真的取决于你想要什么。

      首先,不清楚S_ 来自哪里:也许来自getAllMastersForAgent 的签名?在这种情况下,答案是必要的。但第二个是更根本的问题。

      【讨论】:

      • 感谢您的回复@Alexey Romanov。我在这里要写的是 AgentExecutionListCommand#execute 必须返回 CommandResponseWrapper 的子类型,它也有一些嵌套类型(CommandResponseWrapper[可以是任何类型])。
      • @JorgeCespedes 这似乎正是我在“修复可能只是”段落中所建议的。尝试一下,看看它是否有效。
      • (虽然我没有注意到另一个问题,但 Dima 指出)
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-08-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多