简体   繁体   中英

Scala implicits

I'm trying to understand how to use implicits in Scala: In my code I have:

trait Cell
class EnemyCell extends Cell
class RectangleCell extends Serializable with Cell

I defined a trait Placeable and I wanted it to have a subtype of cell

trait Placeable[A <: Cell] {
  def place(a: A, cell:Option[RectangleCell],controller:MapController ): Unit
}

I then defined the object:

object Placeable {

  //Apply
  def apply[A <: Cell](implicit pleaceable: Placeable[A ]): Placeable[A] = pleaceable
  def place[A: Placeable](a: A, cell:Option[RectangleCell], controller:MapController) = Placeable[A].place(a, cell, controller)


  def instance[A <: Cell](func: (A, Option[RectangleCell], MapController) => Unit): Placeable[A] =
    new Placeable[A] {
      def place(a: A, cell:Option[RectangleCell] , controller: MapController): Unit = func(a, cell, controller)
    }



//These 2 def does not seem to do anything...
  implicit def cellToEnemyCell(cell: Cell): EnemyCell = cell.asInstanceOf[EnemyCell];
  implicit def cellToRectangleCell(cell: Cell): RectangleCell = cell.asInstanceOf[RectangleCell];


  implicit val rectanglePlaceable: Placeable[RectangleCell] =
    instance((selected, cell, controller) => {
      ...
    })

  implicit val enemyPlaceable: Placeable[EnemyCell] =
    instance((selected, cell, controller) => {
      ...
    })
}

The problem is that I am getting the error:

Error:(75, 98) type arguments [A] do not conform to method apply's type parameter bounds [A <: model.Cell]
  def place[A: Placeable](a: A, cell:Option[RectangleCell], controller:MapController) = Placeable[A].place(a, cell, controller)

All I wanted was to use:

var _selected:Option[Cell] = Option.empty; //I edit this in my code and it can be either a RectangleCell or a EnemyCell
...

val tmpRect = _selected.get
place(tmpRect,cell,this)

instead of doing:

      if(_selected.get.isInstanceOf[RectangleCell]) {
        val tmpRect = _selected.get.asInstanceOf[RectangleCell]
        place(tmpRect,cell,this)

      } else {
        val tmpRect = _selected.get.asInstanceOf[EnemyCell]
        place(tmpRect,cell,this)
      }

Thank you in advance!

Here's the fix that gets it to compile.

def place[A <: Cell :Placeable](...

I'm not sure if it gets you where you want to be ( _selected ?) but at least it compiles.

Here's the reason for the error. (I'll use different type parameter designations. Reusing A over and over again can be confusing when they don't necessarily mean the same thing.)

  • trait Placeable[C <: Cell] {... - The Placeable type parameter is restricted to Cell or its sub-types.
  • def place[P: Placeable](... - There must be a Placeable[P] available in the implicit scope. But P is unrestricted. That conflicts with the Placeable definition.

update : No amount of implicit magic is going to resolve your problem because it's a compiler typing issue, unrelated to implicits.

If _selected is type Option[Cell] then _selected.get is type Cell and, as far as the compiler is concerned, that's the end of the story. If there's actually an underlying sub-type here, that can be teased out at run-time.

_selected match {
  case Some(rc:RectangleCell) => place(rc,cell,this)
  case Some(ec:EnemyCell)     => place(ec,cell,this)
  case _ => //some default action
}

Implicits are resolved at compile-time so they can't help discover the underlying type.

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