読者です 読者をやめる 読者になる 読者になる

Xtend の dispatch メソッド

元ネタ:Visitorパターンについて考えた — 裏紙
Xtend なら dispatch という構文 が追加されているので Groovy 位簡単に書けます。

interface Node{}
@Data class NumNode implements Node {
  int value
}
@Data class AddNode implements Node {
  Node right
  Node left
}

class Calculator {
  def dispatch int visit(NumNode node) {
    node.value
  }
  def dispatch int visit(AddNode node) {
    visit(node.left) + visit(node.right)
  }
  def static void main(String... args) {
    val node1 = new NumNode(2)
    val node2 = new NumNode(3)
    val node3 = new AddNode(node1, node2)
    val node4 = new NumNode(4)
    val node5 = new AddNode(node3, node4)
    val calculator = new Calculator()
    val actual = calculator.visit(node5)
    println(actual) // 9
  }
}

生成される .java はこんなのです

import java.util.Arrays;
import org.eclipse.xtext.xbase.lib.InputOutput;

@SuppressWarnings("all")
public class Calculator {
  protected int _visit(final NumNode node) {
    int _value = node.getValue();
    return _value;
  }
  
  protected int _visit(final AddNode node) {
    Node _left = node.getLeft();
    int _visit = this.visit(_left);
    Node _right = node.getRight();
    int _visit_1 = this.visit(_right);
    int _plus = (_visit + _visit_1);
    return _plus;
  }
  public int visit(final Node node) {
    if (node instanceof AddNode) {
      return _visit((AddNode)node);
    } else if (node instanceof NumNode) {
      return _visit((NumNode)node);
    } else {
      throw new IllegalArgumentException("Unhandled parameter types: " +
        Arrays.<Object>asList(node).toString());
    }
  }
  
  public static void main(final String... args) {
    NumNode _numNode = new NumNode(2);
    final NumNode node1 = _numNode;
    NumNode _numNode_1 = new NumNode(3);
    final NumNode node2 = _numNode_1;
    AddNode _addNode = new AddNode(node1, node2);
    final AddNode node3 = _addNode;
    NumNode _numNode_2 = new NumNode(4);
    final NumNode node4 = _numNode_2;
    AddNode _addNode_1 = new AddNode(node3, node4);
    final AddNode node5 = _addNode_1;
    Calculator _calculator = new Calculator();
    final Calculator calculator = _calculator;
    final int actual = calculator.visit(node5);
    InputOutput.<Integer>println(Integer.valueOf(actual));
  }
}

dispatch 付のメソッドは、"_" 付でそれぞれのメソッドが生成され、元の名前では、引数の共通の型で受け instanceOf したコードが生成されます。
パラメータの数が複数でも大丈夫です。
Xtend - Modernized Java Dispatch Methods