【问题标题】:type safe Parsing in javajava中的类型安全解析
【发布时间】:2018-03-17 23:02:58
【问题描述】:

我正在用 java 实现一个解析器。

我正在解析的数据有不同类型的记录。 假设这些是记录类型 A、B、C、... 这些记录有一些共同的属性。所以我正在考虑所有记录A,B,C ..都将实现的接口Record。 文件中的数据如下:

A
B
B
C
C
C
...
X
Y
Z

我正在考虑使用记录迭代器。但它不是类型安全的。 因为我只能拥有

interface Record {
   String getRecordName();
   RecordType recordType();
}
class A implements Record {
    @Override
    String getRecordName() {...}
    // record type 'A' specific methods/fields here
}
class B implements Record{
    @Override
    String getRecordName() {...}
    // record type 'B' specific methods/fields..
}
class Parser implements Iterable<Record> {

    boolean hasNext() {...}
     // user has to examine record type and cast
    Record next() { ...} 
}

有什么办法可以解决这个问题?访客模式在这里有用吗?

编辑: 由于我在这里拥有的是(不同类型的)记录流,所以我仍然想要组合功能。像普通流一样(如 map、filter、takeWhile 等)

编辑: 在考虑了访问者模式之后,我想我得到了另一个想法。 Record 接口将具有accept(Visitor) 方法,next() 将只返回Record(实际类型将是具体的记录类型)。客户端将实现一个访问者并传递给接受方法。

interface Record {

  interface Visitor<R> {
      <R> visit(A a);
      <R> visit(B b);
  }
  // add accept method 
  <R> R accept(Visitor<R> v);
}
class A implements Record {
     @Override
     public <R> R accept(Visitor<R> v) {
          return v.visit(this);
     }
}

// client code; r could be A|B
 Record r = parser.next(); 
 String s = r.accept(new Visitor<String>() { ... });

【问题讨论】:

  • 你试过“实例”吗?
  • 是的,访问者模式在解析器中很常用。
  • "...它不是类型安全的..." 你能解释一下为什么它不是类型安全的吗?
  • 是的,访客模式正是您所需要的。不要使用instanceof。
  • @EmreAcar 是的,我想到了。但有很多类型,我不确定这是最好的方法。在 FP 语言中,模式匹配被认为是惯用的。

标签: java parsing design-patterns


【解决方案1】:

是的:它被称为访问者模式:

public interface RecordVisitor {
    void acceptA(A record);
    void acceptB(B record);
    ...
}

public class Parser {
    public void parse(Reader reader, RecordVisitor visitor) {
        ....
    }
}

...
parser.parse(reader, new RecordVisitor() {
    @Override
    void acceptA(A record) {
        ...
    }
    @Override
    void acceptB(B record) {
        ...
    }
    ...
});
...

【讨论】:

  • 这看起来不可扩展。每次添加新的 Record 类型时,都必须修改接口和(所有)实现。也许访客模式和责任链的混合会更合适。
  • @Turing85 可重新扩展性:这就是为什么经常从语法定义生成这样的代码(对于合理发展的 DSL)。例如,ANTLR 将产生非常大的访问者,实际上,手写起来非常麻烦。
  • 关于可扩展性,对象代数有帮助吗?如果有新的记录类型。
  • @Nyan 我不知道怎么做。无论如何,如果你添加更多的记录类型,你会想要处理它们,所以我认为这不是问题。
猜你喜欢
  • 2020-11-09
  • 2012-04-20
  • 2013-05-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-08-10
相关资源
最近更新 更多