简体   繁体   中英

Scala Override Generic Method from a Trait

I have a trait definition like this:

trait MyTrait {
  def dbService[M[_]]: DBService[M[_]]
  def appConfig: AppConfig
  def supervisorActor: ActorRef
}

I have an implementation of this trait that looks like this:

    object MyTrait {

      def apply(system: ActorSystem, actorMaterializer: Materializer): MyTrait = new MyTrait {

        override val appConfig: AppConfig = AppConfig.load()
// Get the ERROR here saying Value dbService overrides nothing        
override val dbService: DBService[Task] = DBServiceT.asTask(appConfig.dbConfig)(scala.concurrent.ExecutionContext.Implicits.global)

        override val supervisorActor: ActorRef =
          system.actorOf(
            SupervisorActor.props(appConfig)(monix.execution.Scheduler.Implicits.global),
            s"${appConfig.appName}-supervisor"
          )
      }
    }

My DBService trait looks like this:

trait DBService[M[_]] {
  def allPowerPlants(fetchOnlyActive: Boolean): M[Seq[PowerPlantRow]]
  def powerPlantsPaginated(filter: PowerPlantFilter): M[Seq[PowerPlantRow]]
  def allPowerPlantsPaginated(fetchOnlyActive: Boolean, pageNumber: Int): M[Seq[PowerPlantRow]]
  def powerPlantById(id: Int): M[Option[PowerPlantRow]]
  def newPowerPlant(powerPlantRow: PowerPlantRow): M[Int]
}

I then have an implementation that looks like this:

class DBServiceTask private (dbConfig: DBConfig)(implicit ec: ExecutionContext) extends DBService[Task] { self =>

....
....

}

When I tried this, I get an error in my MyTrait object that says:

Value dbService overrides nothing

Any ideas what I'm doing wrong?

This signature:

def dbService[M[_]]: DBService[M[_]]

describes something that can create a DBService for ANY type constructor M[_] . For it to typecheck it must be able to create all of:

  • DBService[Task]
  • DBService[Future]
  • DBService[Array]
  • DBService[Option]
  • DBService[Ordering]
  • ...and so on

Since your implementation can only produce a value for a single M[_] ( Task in your case), you cannot have that signature.

Your options include moving a type parameter to a trait definition, either as a type parameter:

trait MyTrait[M[_]] {
  def dbService: DBService[M] // also note that [_] part should not be here
}

or a type member:

trait MyTrait {
  type M[_]
  def dbService: DBService[M]
}

The latter, however, might be a nuisance to use

EDIT : You also have the option of specifying Task directly, of course:

trait MyTrait {
  def dbService: DBService[Task]
}

val dbService: DBService[Task] is a value of type DBService[Task] , whereas you need to define a function that takes a type as "parameter": def dbService[M[_]]: DBService[M[_]]

I think you want your trait to look like this:

trait MyTrait[M[_]] {
  def dbService: DBService[M[_]]
  def appConfig: AppConfig
  def supervisorActor: ActorRef
}

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