How to implement two interfaces with same method name and different arguments

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

How to implement two interfaces with same method name and different arguments

问题

我有两个不同的接口(来自两个不同的包),我想要实现它们。但是它们发生了冲突,就像这样:

type InterfaceA interface {
  Init()
}

type InterfaceB interface {
  Init(name string)
}

type Implementer struct {} // 想要实现 A 和 B

func (i Implementer) Init() {}

func (i Implementer) Init(name string) {} // 编译器报错

它说"方法重复声明"。如何让一个结构体实现这两个接口呢?

英文:

I have two different interfaces (from two different packages) that I want to implement. But they conflict, like this:

type InterfaceA interface {
  Init()
}

type InterfaceB interface {
  Init(name string)
}

type Implementer struct {} // Wants to implement A and B

func (i Implementer) Init() {}

func (i Implementer) Init(name string) {} // Compiler complains

It says "Method redeclared". How can one struct implement both interfaces?

答案1

得分: 6

如前所述,这是不可能的,因为Golang不支持(也可能永远不会支持)方法重载。

请参考Golang FAQ

从其他语言的经验来看,拥有多个具有相同名称但不同签名的方法有时可能很有用,但在实践中可能会令人困惑和脆弱。在Go的类型系统中,只通过名称匹配并要求类型一致是一个重要的简化决策。

英文:

As already answered, this is not possible since Golang does not (and probably will not) support method overloading.

Look at Golang FAQ:

> Experience with other languages told us that having a variety of methods with the same name but different signatures was occasionally useful but that it could also be confusing and fragile in practice. Matching only by name and requiring consistency in the types was a major simplifying decision in Go's type system.

答案2

得分: 3

这是要翻译的内容:

这是不可能的。

在Go语言中,你必须有一个单一的方法签名。

你应该重命名一个方法。

英文:

It is not possible.

In go you must have a single method signature.

You should rename one method.

答案3

得分: -1

方法签名必须匹配。如果你想要依赖注入,我建议使用函数选项模式(functional option pattern)。函数选项是返回其他函数的函数,在构造函数中循环调用这些函数。以下是如何使用函数选项和Go语言接口的基础知识的示例。

package main

import (
	"fmt"
	"strconv"
)

type SomeData struct {
	data string
}

type SomeInterface interface {
	String() string
	Set(data string)
}

func (s *SomeData) String() string {
	return s.data
}

func (s *SomeData) Set(data string) {
	s.data = data
}

func SetDataOption(data string) func(*SomeData) {
	return func(s *SomeData) {
		s.Set(data)
	}
}

func NewSomeData(options ...func(s *SomeData)) SomeInterface {
	s := new(SomeData)

	for _, o := range options {
		o(s)
	}
	return s
}

type SomeOtherData struct {
	data string
	i    int
}

type SomeOtherInterface interface {
	String() string
	Set(data string)
}

func (s *SomeOtherData) String() string {
	return s.data + "  " + strconv.Itoa(s.i)
}

func (s *SomeOtherData) Set(data string) {
	s.data = data
}

func SetOtherDataOption(data string) func(*SomeOtherData) {
	return func(s *SomeOtherData) {
		s.Set(data)
	}
}

func SetOtherIntOption(i int) func(*SomeOtherData) {
	return func(s *SomeOtherData) {
		s.i = i
	}
}

func NewSomeOtherData(options ...func(s *SomeOtherData)) SomeOtherInterface {
	s := new(SomeOtherData)

	for _, o := range options {
		o(s)
	}
	return s
}

func HandleData(si SomeInterface) {
	fmt.Println(si)
}

func main() {
	someData := NewSomeData(SetDataOption("Optional constructor dep"))
	someOtherData := NewSomeOtherData(SetOtherDataOption("Other optional constructor dep"), SetOtherIntOption(42))
	HandleData(someData)
	HandleData(someOtherData)
	someOtherData = someData
	HandleData(someOtherData)
}

以上是一个使用函数选项和接口的示例代码。

英文:

The method signatures must match. If you want dependency injection I would recommend the functional option pattern. Functional options are functions that return other functions that are called in a loop in the constructor. Here is an example of how to use functional options and the basics of interfaces in go.

package main
import (
"fmt"
"strconv"
)
type SomeData struct {
data string
}
// SomeData and SomeOtherData both implement SomeInterface and SomeOtherInterface
// SomeInterface and SomeOtherInterface both implement each other.
type SomeInterface interface {
String() string
Set(data string)
}
func (s *SomeData)String() string {
return s.data
}
func (s *SomeData)Set(data string)  {
s.data = data
}
// SetDataOption is a functional option that can be used to inject a constructor dep
func SetDataOption(data string) func(*SomeData) {
return func(s *SomeData) {
s.Set(data)
}
}
// NewSomeData is the constructor; it takes in 0 to many functional options and calls each one in a loop.
func NewSomeData(options ...func(s *SomeData)) SomeInterface {
s := new(SomeData)
for _, o := range options {
o(s)
}
return s
}
//********************
type SomeOtherData struct {
data string
i    int
}
type SomeOtherInterface interface {
String() string
Set(data string)
}
func (s *SomeOtherData)String() string {
return s.data + "  " + strconv.Itoa(s.i)
}
func (s *SomeOtherData)Set(data string)  {
s.data = data
}
func SetOtherDataOption(data string) func(*SomeOtherData) {
return func(s *SomeOtherData) {
s.Set(data)
}
}
func SetOtherIntOption(i int) func(*SomeOtherData) {
return func(s *SomeOtherData) {
s.i = i
}
}
// NewSomeOther data works just like NewSomeData only in this case, there are more options to choose from
// you can use none or any of them.
func NewSomeOtherData(options ...func(s *SomeOtherData)) SomeOtherInterface {
s := new(SomeOtherData)
for _, o := range options {
o(s)
}
return s
}
//*********************************
// HandleData accepts an interface
// Regardless of which underlying struct is in the interface, this function will handle 
// either by calling the methods on the underlying struct.
func HandleData(si SomeInterface) {
fmt.Println(si)  // fmt.Println calls the String() method of your struct if it has one using the Stringer interface
}
func main() {
someData := NewSomeData(SetDataOption("Optional constructor dep"))
someOtherData := NewSomeOtherData(SetOtherDataOption("Other optional constructor dep"), SetOtherIntOption(42))
HandleData(someData) // calls SomeData.String()
HandleData(someOtherData) // calls SomeOtherData.String()
someOtherData = someData // assign the first interface to the second, this works because they both implement each other.
HandleData(someOtherData) // calls SomeData.String()  because there is a SomeData in the someOtherData variable.
}

huangapple
  • 本文由 发表于 2022年4月27日 03:25:43
  • 转载请务必保留本文链接:https://go.coder-hub.com/72019486.html
匿名

发表评论

匿名网友

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

确定