基于接口抽象实现一个'Stringer'

Implement a 'Stringer' abstractly based on an interface

我正在尝试实现一个接口 'abstractly'。我的意思是我试图根据另一个接口的方法来实现该接口的方法。

这是我尝试过的方法(但它不起作用,因为似乎我们不允许使用接口类型作为接收者):

package symbols

import "fmt"

type Symbol interface {
    Name() string
}

type TerminalSymbol struct {
    rune rune
}

func (t TerminalSymbol) Name() string {
    return `'` + string(t.rune) + `'`
}

type NonTerminalSymbol struct {
    name string
}

func (nt NonTerminalSymbol) Name() string {
    return nt.name
}

/////////////////////////////////////////////////////////
/// Try to implement 'Stringer' interface for Symbols

func (s Symbol) String() string {
    //^ ERROR: invalid receiver type Symbol (pointer or interface type)
    return fmt.Sprintf("A symbol with name: %v", s.Name())
}

我想 go 编译器本质上是在告诉我,根本不支持基于另一个接口实现一个接口?

我想我可以简单地接受提示并改为这样做:

func (s NonTerminalSymbol) String() string {
    return fmt.Sprintf("A symbol with name: %v", s.Name())
}

func (s TerminalSymbol) String() string {
    return fmt.Sprintf("A symbol with name: %v", s.Name())
}

可行,但最终会重复 'String' 方法的实施。

在Java中我们可以很容易地避免这种重复;例如通过向抽象中添加具体方法 class;或者通过向接口中的某些方法添加 'default' 实现。

有没有一种'idiomatic'的方法可以在go中完成这种事情? (也就是说,我们能否使抽象类型如 Symbol 实现 Stringer 而无需复制 String() 的实现。

您不能拥有类似于调用具体实现方法的抽象基 class 的结构。有很多方法可以模拟,但我猜这不是你要问的。

在Go中,接口只是一个方法列表,不存在class继承的概念。您可以使用类型嵌入构建对象层次结构,但这不提供实现此功能所需的后期绑定。

但是,您可以这样做:

为符号创建纵梁函数:

func SymbolToString(s Symbol) string {
       return fmt.Sprintf("A symbol with name: %v", s.Name())
}

现在您可以为每个结构编写 String 方法的简单实现:

type NonTerminalSymbol struct {
    name string
}

func (n NonTerminalSymbol) String() string {return SymbolToString(n)}