在这种情况下是否可以“隐藏”此通用类型参数?

时间:2016-03-24 16:47:44

标签: java generics

项目是这样的:

https://github.com/ChrisBrenton/grappa-parsetree

目标是为最终用户提供API,使得包易于使用。目前,this是提案。

首先,使用示例:

final ParseTree<Void, SentenceNode> parseTree = ParseTree
    .usingParser(SentenceParser.class)
    .withRule(SentenceParser::sentence)
    .withRoot(SentenceNode.class);

通过上面的链接实现此目的的代码在这里复制(省略了import / package声明):

ParseTree.java

public final class ParseTree<T, N extends ParseNode>
{
    private final Rule rule;
    private final ParseNodeConstructorProvider provider;
    private final Class<N> nodeClass;

    public static <T, P extends BaseParser<T>> ParseTreeBootstrap<T, P>
        usingParser(final Class<P> parserClass)
    {
        Objects.requireNonNull(parserClass);
        return new ParseTreeBootstrap<>(parserClass);
    }

    ParseTree(final Rule rule, final ParseNodeConstructorProvider provider,
        final Class<N> nodeClass)
    {
        this.rule = rule;
        this.provider = provider;
        this.nodeClass = nodeClass;
    }

    public N parse(final CharSequence input)
    {
        final ParseRunner<T> runner = new ParseRunner<>(rule);

        final ParseTreeBuilder<T> builder = new ParseTreeBuilder<>(provider);

        runner.registerListener(builder);

        if (!runner.run(input).isSuccess())
            throw new GrappaException("parsing failed! Cannot retrieve the tree");

        return nodeClass.cast(builder.getTree());
    }
}

ParseTreeBootstrap.java

public final class ParseTreeBootstrap<T, P extends BaseParser<T>>
{
    private final P parser;
    private final ParseNodeConstructorProvider provider;

    ParseTreeBootstrap(final Class<P> parserClass)
    {
        parser = Grappa.createParser(parserClass);
        provider = new ParseNodeConstructorProvider(parserClass);
    }

    public ParseTreeRule<T, P> withRule(final Function<? super P, Rule> fn)
    {
        Objects.requireNonNull(fn);
        return new ParseTreeRule<>(parser, provider, fn);
    }
}

ParseTreeRule.java

public final class ParseTreeRule<T, P extends BaseParser<T>>
{
    private final Rule rule;
    private final ParseNodeConstructorProvider provider;

    ParseTreeRule(final P parser, final ParseNodeConstructorProvider provider,
        final Function<? super P, Rule> fn)
    {
        rule = fn.apply(parser);
        this.provider = provider;
    }

    public <N extends ParseNode> ParseTree<T, N> withRoot(final Class<N> nodeClass)
    {
        Objects.requireNonNull(nodeClass);
        return new ParseTree<>(rule, provider, nodeClass);
    }
}

我在这里遇到的问题是ParseTree的初始声明:

final ParseTree<Void, SentenceNode> parseTree = ...

第一个类型参数是因为它是解析器本身的类型参数:

public class SentenceParser
    extends BaseParser<Void>

但是在生成解析树时,此类型与最终用户无关。

我试图忽略它,但问题来自ParseTree中的这个方法:

    public N parse(final CharSequence input)
    {
        final ParseRunner<T> runner = new ParseRunner<>(rule);

        final ParseTreeBuilder<T> builder = new ParseTreeBuilder<>(provider);

        runner.registerListener(builder);

        if (!runner.run(input).isSuccess())
            throw new GrappaException("parsing failed! Cannot retrieve the tree");

        return nodeClass.cast(builder.getTree());
    }

我无法在N替换?,因为如果我这样做,那么我就不能.registerListener()(捕获不同)。

一种解决方案可能是使用原始类型;但是如果可能的话,我想避免这种情况。

您如何避免在此声明第一个类型参数?

0 个答案:

没有答案