score:1

Accepted answer

Would this suffice? (It compiles...)

/* Classes defined by the framework */
abstract class Node {
    def getMessage(n: Node): Int
}

def importantAlgorithm(lstNodes1: List[Node], lstNodes2: List[Node]) {
  lstNodes1.zip(lstNodes2).map {
    case (n1, n2) =>
      // I would like to get the proper message *BASED ON
      // THE TYPE OF N1 and N2*
      val message = n1.getMessage(n2)
  }
}

/* Classes defined by framework users */
class   ItemNode(val p: Int)
extends Node
{
  def getMessage(n: Node): Int =
    n match {
    // Compute message based on this ItemNode member variables
    // and n (instance of UserNode) member variables
      case un: UserNode => 0
      case in: ItemNode => 1
      case xn: Node     => -1
  }
}

class   UserNode
extends Node
{
  def getMessage(n: Node): Int =
    n match {
      case on: OtherNode => 23
      case xn: Node     => -1
    }
}

class   OtherNode
extends Node
{
  def getMessage(n: Node): Int =
    n match {
      case xn: Node => 514
    }
}

// The user should be able to use the framework this way
importantAlgorithm(List(new UserNode(),
                        new ItemNode(236),
                        new OtherNode()),
                   List(new OtherNode(),
                        new ItemNode(542),
                        new UserNode()))

score:1

I think you need is something like

trait Node {
  type AppropriateSender <: Node
  def getMessage(n: AppropriateSender): Int
}

class UserNode extends Node {
  type AppropriateSender = OtherNode
  def getMessage(n: OtherNode) = ???
}

...

However, there are some problems caused by type erasure so that you cannot check the compatibility of your n1 and n2 (maybe type tags?), but at least you can implement your staff in a clean way now. Another issue is how you deal with the fact that some node types have more than 1 appropriate sender type (which might be solved by an implementation of raw union type).


Related Query

More Query from same tag