根据接口实现一个抽象的 “Stringer”。

huangapple go评论87阅读模式
英文:

Implement a 'Stringer' abstractly based on an interface

问题

我正在尝试以“抽象”的方式实现一个接口。我的意思是,我试图根据另一个接口的方法来实现该接口的方法。

这是我尝试过的代码(但它不起作用,因为似乎不允许将接口类型用作接收器):

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
}

/////////////////////////////////////////////////////////
/// 尝试为 Symbols 实现 'Stringer' 接口

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中,我们可以很容易地避免这种重复;例如,通过向抽象类添加具体方法,或者通过为接口中的某些方法添加“默认”实现。

在go中,是否有一种“惯用”的方法来实现这种类型的操作?也就是说,我们是否可以使类似Symbol的抽象类型实现Stringer而不重复实现String()方法?

英文:

I am trying to implement an interface 'abstractly'. What I mean by that is that I am trying to implement the method(s) of that interface in terms of methods of another interface.

Here's what I tried (but it doesn't work because it seems we are not allowed to use a Interface type as a receiver):

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())
}

I suppose go compiler is essentially telling me that implementing one interface based on another interface is simply not supported?

I suppose I could simply take the hint and just do this instead:

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())
}

That works, but it ends up duplicating the implementation of the 'String' method.

In Java we can easily avoid this kind of duplication; e.g. by adding concrete methods to an abstract class; or by adding a 'default' implementation to some of the methods in an interface.

Is there an 'idiomatic' way to accomplish this kind of thing in go? (i.e. can we make an abstract type like Symbol implement Stringer without duplicating the implementation of String().

答案1

得分: 4

你不能拥有一个类似于抽象基类的结构,它调用具体实现的方法。有一些方法可以模拟这个过程,但我猜这不是你的问题所在。

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

然而,你可以这样做:

为符号创建一个字符串转换函数:

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)}
英文:

You cannot have a structure similar to an abstract base class that calls the methods of the concrete implementation. There are ways to emulate that, but I am guessing that's not what you are asking.

In Go, an interface is simply a method list, and the concept of class inheritance does not exist. You can build object hierarchies using type embedding, but that does not provide the late binding you need to implement this.

However, you can do this:

Create a stringer function for symbols:

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

Now you can write simple implementation of String method for each struct:

type NonTerminalSymbol struct {
    name string
}

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

huangapple
  • 本文由 发表于 2022年4月4日 08:54:09
  • 转载请务必保留本文链接:https://go.coder-hub.com/71731006.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定