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 ではメソッドのパラメーターをサブクラスに特殊化することは許可されておらず、上記のコードはコンパイルされません。または RTTIを使用できますisInstanceOf[]が、適切に考えておらず、フレームワークを適切に設計していないと感じています。上記のコード サンプルで説明されているメカニズムを、よりシンプルでクリーンなソリューションに置き換えるにはどうすればよいでしょうか?

4

2 に答える 2

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 に答える
1

私はあなたが必要だと思う

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

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

...

ただし、型の消去によって引き起こされるいくつかの問題があり、n1and n2(おそらく型タグ?) の互換性を確認できませんが、少なくとも、クリーンな方法でスタッフを実装できるようになりました。もう 1 つの問題は、一部のノード タイプに複数の適切な送信者タイプがあるという事実にどのように対処するかです (生のユニオン タイプの実装によって解決される可能性があります)。

于 2013-02-14T18:09:00.663 に答える