【问题标题】:Trouble with generics when trying port the LOX language implementation from the Crafting Interpreter's book to C#尝试将 LOX 语言实现从 Crafting Interpreter 的书中移植到 C# 时出现泛型问题
【发布时间】:2017-07-21 01:56:27
【问题描述】:

我最近发现了语言错误,作为学习过程的一部分,我开始阅读 Bob Nystrom 的 Crafting Interpreters 书,并尝试用 C# 重新创建 JLOX 语言解释器。

JLOX 中的“J”是指本书中的示例代码是用 Java 实现的。

在本书的“使用树”和“A(不是非常)漂亮的打印机”部分,Bob 介绍了访问者模式作为“表达式问题”的解决方案。

我曾尝试将 Java 代码翻译成 C#,但现在遇到以下编译器错误:

"ASTPrinter.VisitBinaryExpr(Expression.Binary): No suitable method found to override" (点击查看图片)

两个相关的代码文件是:

Expression.cs

使用系统;

namespace CSharpLox
{
    abstract public class Expression
    {
        abstract public T Accept<T>(Visitor<T> visitor);

        public interface Visitor<T>
        {
            T VisitBinaryExpr(Binary expr);
            // other expression type visitors removed for clarity...
        }

        public class Binary : Expression
        {
            public readonly Expression left;
            public readonly Token _operator;
            public readonly Expression right;

            public Binary(Expression left, Token _operator, Expression right)
            {
                this.left = left;
                this._operator = _operator;
                this.right = right;
            }

            override public T Accept<T>(Visitor<T> visitor)
            {
                return visitor.VisitBinaryExpr(this);
            }
        }

        // other expression types removed for clarity...
    }
}

还有 ASTPrinter.cs

using System;
using System.Text;

namespace CSharpLox
{
    // ASTPrinter.cs
    public class ASTPrinter : Expression.Visitor<string>
    {
        override public string VisitBinaryExpr(Expression.Binary expression)
        {
            return parenthesize(expression._operator.lexeme, expression.left, expression.right);
        }

        private String parenthesize(String name, params Expression[] expressions)
        {
            StringBuilder builder = new StringBuilder();

            builder.Append("(").Append(name);

            foreach (Expression expression in expressions)
            {
                builder.Append(" ");
                builder.Append(expression.Accept(this));
            }

            builder.Append(")");

            return builder.ToString();
        }
    }
}

ASTPrinter.cs这行我不知道怎么解决的错误:

覆盖公共字符串 VisitBinaryExpr(Expression.Binary 表达式)

Visual Studio 编辑器报告的错误文本是:

错误 CS0115 'ASTPrinter.VisitBinaryExpr(Expression.Binary)':找不到合适的方法来覆盖

我想我只是对 C# 泛型返回类型了解不够。

我一直在四处寻找有关泛型返回类型的信息,但到目前为止,我还没有找到一个清楚的例子来说明它如何与抽象接口的具体实现进行交互。或者,这可能是 C# 和 Java 的泛型功能差异太大而无法直接翻译实现的一个领域。

任何建议将不胜感激。

【问题讨论】:

  • 在你的Visitor&lt;T&gt;界面,试试public T VisitBinaryExpr(Binary expr);,可能是访问问题。
  • 注意Java方法默认是虚拟的,C#方法默认是非虚拟的。似乎T VisitBinaryExpr(Binary expr); 没有设置为公共和虚拟。 (此外,Java 泛型类型的行为与 C# 泛型类型不同,请注意这一点)。
  • @KeyurPATEL 按照建议添加公共会导致在VisitBinaryExpr(Binary expr); 上出现编译器错误Modifier public is not valid for this item
  • @TetsuyaYamamoto 我认为你是对的!错误消息的实际文本给出了提示:“没有找到合适的方法来覆盖”。当我从 ASTPrinter.cs 中的方法实现中删除“覆盖”时,错误已修复!!我猜 C# 中的“接口”不是虚拟的,所以这就是为什么不需要指定覆盖。谢谢!请添加答案,以便我将您标记为正确。

标签: c# generics interpreter expressionvisitor


【解决方案1】:

你的Expression.Visitor&lt;string&gt; 是一个接口,所以没有什么可以覆盖的。

简单地说:

public string VisitBinaryExpr(Expression.Binary expression)

只有当基类已经定义了一个与声明为vitrualabstract的签名相同的方法时,您才需要override

在您的情况下,ASTPrinter 类直接派生自 System.Object

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2010-10-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多