Java静态绑定使得实现Composite变得尴尬

时间:2018-02-09 15:33:58

标签: java polymorphism composite

我有类似这样的类结构:

interface Composite {}

class Leaf implements Composite { public String val; }

class Node implements Composite {
    private Node parent;
    private Composite left;
    private Composite right;

    public void attachLeft(Composite c) {
         left = c;
    }
    public void attachRight(Composite c) {
         right = c;
    } 
    public void attachLeft(Node n) {
         left = n;
         n.parent = this;
    }
    public void attachRight(Node n) {
         right = n;
         n.parent = this;
    }
    public void attachRandomly(Composite c) {
         if ( ThreadLocalRandom.current().nextBoolean() ) {
             attachRight(c);
         } else {
             attachLeft(c);
         }
    }
}

我有一个生成随机树(伪代码)的方法:

// build tree
for some number of nodes :
    make newNode
    oldNode = randomly pick an existing node with an empty right/left 
    oldNode.attachRandomly(newNode)

// fill leaves of tree
for each node with empty right/left :
    while node has empty right/left :
        node.attachRandomly(new Leaf)

不幸的是,由于静态绑定,attachLeft / Right(Node c)方法永远不会被attachRandomly调用。 (attachRandomly正在获取一个Composite,因此始终会调用attachLeft / Right的复合版本。)所以我的父属性永远不会被设置。

现在,我可以想出几种方法来完成这项工作:

  1. 删除attachLeft / Right的Node版本,只使用复合版本中的instanceof和cast
  2. 添加特定于节点的attachRandomly版本
  3. 选项1感觉很难吃(instanceof!cast!)而选项2只是因为额外代码的数量而感到尴尬。有没有更好的方法来做到这一点,以便多态可以启动并帮助我在这里?

1 个答案:

答案 0 :(得分:1)

你可以这样写。这个基本思想叫做 double dispatching 。它为每个方法调用引入了一个新级别的调度,以允许使用动态绑定。

interface Composite {
    void attachToLeft(Node newParent);
    void attachToRight(Node newParent);
}

class Leaf implements Composite { 
    public String val;
    @Override
    public void attachToLeft(Node newParent) {
        newParent.left = this;
    }
    @Override
    public void attachToRight(Node newParent) {
        newParent.right = this;
    }
}

class Node implements Composite {
    private Node parent;
    private Composite left;
    private Composite right;

    public void attachLeft(Composite c) {
         c.attachToLeft(this);
    }
    public void attachRight(Composite c) {
         c.attachToRight(this);
    } 
    @Override
    public void attachToLeft(Node newParent) {
         this.parent = newParent;
         newParent.left = this;
    }
    @Override
    public void attachToRight(Node newParent) {
         this.parent = newParent;
         newParent.right = this.
    }
}