1

我想创建一个框架,用户可以在其中对基类进行子类化,Node该基类能够根据当前实例状态和另一个实例的属性(参数 n)生成消息(此处为整数)。用户应该能够根据当前实例的类和参数 n 的类getMessage来专门化该方法以生成不同的消息,如下面的代码所示。

该函数importantAlgorithm使用这些节点生成的消息来计算最终结果。

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

def importantAlgorithm(lstNodes1: List[_ <: Node], lstNodes2: List[_ <: Node]) = {

    val results = 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)
        // Do some work with the message
        //...
        //...
        })
    //...
}

// Classes defined by framework users //
class ItemNode(val p: Int) extends Node {
    override def getMessage(n: UserNode) = {
        // Compute message based on this ItemNode member variables
        // and n (instance of UserNode) member variables
    }
    override def getMessage(n: ItemNode) = {
        // Compute message based on this ItemNode member variables
        // and n (instance of UserNode) member variables
        // The algorithm is different from the algorithm
        // used in the previous method
    }
}

class UserNode extends Node {
    override def getMessage(n: OtherNode) = {
        // Compute message. Same idea as above
    }
}

class OtherNode extends Node { 
    override def getMessage(n: UserNode) = {
        // Compute message. Same idea as above
    }
}

// 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()))

当然,Scala 不允许在子类中特化方法的参数,上述代码无法编译。我可以使用isInstanceOf[]或 RTTI,但我觉得我没有正确思考并且没有正确设计我的框架。如何用更简单、更清洁的解决方案替换上面代码示例中描述的机制?

4

2 回答 2

1

我认为你需要的是类似的东西

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

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

...

但是,类型擦除会导致一些问题,因此您无法检查n1n2(可能是类型标签?)的兼容性,但至少您现在可以以干净的方式实现您的人员。另一个问题是您如何处理某些节点类型具有超过 1 个适当的发送者类型的事实(这可以通过实现raw union type来解决)。

于 2013-02-14T18:09:00.663 回答
1

这样就够了吗?(它编译...)

/* 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()))
于 2013-02-14T18:56:25.943 回答