Реализация метода toString в Java с помощью шаблона посетителя? - PullRequest
3 голосов
/ 21 октября 2011

Вот мой код на Java

public List<OBJ> a = new ArrayList<OBJ>();
public String A;
public String B;
public String C;
for (OBJ o : a) {
    // .... TODO
}

Итак, у меня есть интерфейс OBJ, и есть три объекта, которые реализуют OBJ, скажем, X, Y, Z. Поэтому я храню объекты X / Y / Z в Списке а. Теперь скажите, что я хочу пройти через цикл, и если o имеет экземпляр X, сохранить X.value в A, если Y сохранить Y.value в B, и если Z сохранить Z.value в C. Так что проблема в том, как сделать Вы выясняете, какой тип объекта o (X, Y, Z), чтобы хранить их значения в правой строке.

ПРИМЕЧАНИЕ. Я хочу использовать шаблон Visitor или что-то в этом роде, но я не совсем понимаю, поэтому прошу вашей помощи.

Это означает, что НЕТ экземпляров или типов и НЕТ специальных методов, таких как

interface OBJ {
    void blah();
}

class X implements OBJ {
    public void blah();
} // etc

Спасибо! Я действительно хочу избавиться от этого аспекта разработки программного обеспечения!

Эй, вау, спасибо за подробные и быстрые ответы, но моя ситуация немного сложнее, и извините, я не добавил это раньше.

Таким образом, строки A, B, C на самом деле находятся в другом классе, например

class ARGH {
    public List<OBJ> a = new ArrayList<OBJ>();
    public String A;
    public String B;
    public String C;
    //invisible constructor here
    public String toString () {
        for (OBJ o : a) {
            // .... TODO
        }
        return "some string"
    }
}
public void main (String[] args) {
    ARGH argh = new ARGH();
    // Setup some X, Y, Z objects and their values here
    String D = argh.toString();
    // Do something to D
}

Таким образом, строки и список на самом деле не являются глобальными переменными, поэтому я не думаю, что это сработает:

ObjVisitor v = new ObjVisitor() {
    @Override
    public void visit(X x) {
      A = x.value();
    }
    // And so on.
}

Я предполагаю, что мне нужно как-то передать строку A, B, C в метод посещения, но я не знаю, как это сделать, и все еще оставаться с шаблоном Visitor.

Ответы [ 2 ]

3 голосов
/ 21 октября 2011

В ореховой скорлупе вы должны сделать следующее:

  1. Создать интерфейс Visitor ObjVisitor с одним visit -методом для каждого типа.
  2. Добавитьаннотация accept(ObjVisitor v) до OBJ.
  3. Добавление accept(ObjVisitor v) { v.visit(this); } к каждой OBJ реализации.
  4. Вызов o.accept(yourVisitorImpl) в цикле.

Вы действительно действительно получили код от Bringer128.Я немного уточнил и добавил String -stuff.

import java.util.*;

interface OBJ {
    String accept(ObjVisitor v);
}

interface ObjVisitor {
    String visit(X x);
    String visit(Y y);
    String visit(Z z);
}

class X implements OBJ {
    public String accept(ObjVisitor v){ return v.visit(this); }
}
class Y implements OBJ {
    public String accept(ObjVisitor v) { return v.visit(this); }
}
class Z implements OBJ {
    public String accept(ObjVisitor v) { return v.visit(this); }
}

Использование:

class Test {
    public static void main(String[] args) {

        List<OBJ> objs = Arrays.asList(new Z(), new X());

        ObjVisitor toStringVisitor = new ObjVisitor() {
            public String visit(X x) { return "X object"; }
            public String visit(Y y) { return "Y object"; }
            public String visit(Z z) { return "Z object"; }
        };

        String result = "";
        for (OBJ o : objs)
            result += o.accept(toStringVisitor) + "\n";

        System.out.println(result);

        // Prints
        // Z object
        // X object
    }
}

Альтернативным (возможно, лучшим подходом) будет позволить реализации посетителя поддерживать StringBuilder, пусть методы посещения возвращают void, и после цикла просто вызовите stringVisitor.getCurrentString() или что-то в этом роде.

0 голосов
/ 21 октября 2011

aioobe разъяснил это для вас, но вот как будет выглядеть реализация.

interface OBJ {
  void blah();
  // New method!
  void accept(ObjVisitor v);
}

class X implements OBJ {
  public void blah() {}
  @Override
  public void accept(ObjVisitor v) {
    v.visit(this);
  }
}

interface ObjVisitor {
  public void visit(X x);
  public void visit(Y y);
}

Теперь используйте его:

public List<OBJ> a = new ArrayList<OBJ>();
public String A;
public String B;
public String C;

public void myMethod() {

  ObjVisitor v = new ObjVisitor() {
    @Override
    public void visit(X x) {
      A = x.value();
    }
    // And so on.
  }
  for (OBJ o : a) {
    o.accept(v);
  }
}
...