简体   繁体   中英

Scala generic type parameters issues

I'm relatively new to Scala and I'm having issues with generic type parameters. I'm implementing command pattern for certain operations and I have a base class like this:

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 }]
}

Now, take this concrete command as a sample of the issues I'm having:

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

The method getAllMastersForAgent in the repository, returns a Future[Seq[AgentExecution]], but the compiler shows an error in this line:

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

The error is: Expression of type AgentExecutionListResponse[Seq] doesn't conform to expected type S_

What does that mean?

Another error is:

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){

Why does it say that it takes no type parameters and then again, expects one. I don't get it. Please help!

Thanks in advance!

The problem is here:

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

The [...] thingy should be after CommandResponseWrapper not after the class name

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

For the second error:

T[X] <: CommandResponseWrapper[X] forSome { type X } means you told the compiler T has to be a type constructor with a single parameter (that's why you can write T[X] in execute 's signature), but AgentExecutionListResponse[Seq[AgentExecution]] doesn't take parameters (you can't write AgentExecutionListResponse[Seq[AgentExecution]][SomeType] ). So you can't use it as T . Just as if you try to call foo() where foo has a parameter.

Also, I think that the scope of X in forSome is just CommandResponseWrapper[X] forSome { type X } , so it's the same as T[X] <: CommandResponseWrapper[_] . So naming X in T[X] is confusing.

Given the signature you expect for AgentExecutionListCommand#execute , the fix might be just

abstract class Command[A, B <: BaseModel, T <: CommandResponseWrapper[_]](repository: BaseRepository[A, B], entity: B) {

  @throws(classOf[Exception])
  def execute: Future[T]
}

but it really depends on what you want.

For the first, it isn't clear where S_ comes from: perhaps from getAllMastersForAgent 's signature? In that case it would be necessary for the answer. But the second is a more fundamental issue.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM