为什么将两个使用相同方法的命名接口视为不同的接口,又如何避免呢?
假设我们有一个喜欢吃产品的人(食者)。他不在乎产品是什么,他只想指出从哪里可以买到新产品。换句话说,他想要产品服务,但并不关心产品服务将生产什么产品。在具体的实现中,我们将尝试用苹果喂他,因此我们将为他提供appleService。
结果如下:
./main.go:9: cannot use appleService (type *service.AppleService) as type eater.ProductServiceI in function argument: *service.AppleService does not implement eater.ProductServiceI (wrong type for New method) have New() service.ProductI want New() eater.ProductI
接口service.AppleI和eater.AppleI具有相同的方法Eat(),除了golang之外,别无其他。为什么以及如何避免这种情况?根据鸭子的说法,这应该起作用,因为实际ProductServiceI需要的是提供的struct具有Eat()方法- 它不必关心名称具有接口(service.ProductIvs eater.ProductI)。
service.AppleI
eater.AppleI
Eat()
ProductServiceI
service.ProductI
eater.ProductI
下面是完整的代码:
==> ./main.go <==
package main import "./apple/service" import "./eater" func main() { appleService := &service.AppleService{} // func eater.New(productService ProductServiceI) appleEater := eater.New(appleService) appleEater.EatUntilHappy() }
==> ./eater/eater.go <==
package eater type ProductServiceI interface { New() ProductI } type ProductI interface { Eat() } type Eater struct { productService ProductServiceI } func New(productService ProductServiceI) *Eater { return &Eater{ productService: productService, } } func (a *Eater) EatUntilHappy() { for i:=0; i < 5; i++ { product := a.productService.New() product.Eat() } }
==> ./apple/service/service.go <==
package service import "./apple" type ProductI interface { Eat() } type AppleService struct { } func (a *AppleService) New() ProductI { return &apple.Apple{} }
==> ./apple/service/apple/apple.go <==
package apple import "fmt" type Apple struct { } func (a *Apple) Eat() { fmt.Println("mniam, mniam") }
我认为,只要声明相同,什么名称或导入路径都有接口都没有关系。
我会回答我自己的问题
首先,我只是在官方常见问题解答中找到了关于这些接口为何不被视为相似的答案:http : //golang.org/doc/faq#t_and_equal_interface
其次,在我的情况下,我可以使用匿名接口interface { Eat() }代替声明type ProductI interface { Eat() }
interface { Eat() }
type ProductI interface { Eat() }
但是,如果出现来自go faq的示例 ,则不可能 。考虑一下:
type Equaler interface { Equal(Equaler) bool } type T int func (t T) Equal(u Equaler) bool { return t == u.(T) }
如果您在这里使用相同的技巧,您将获得
type T int func (t T) Equal(u interface{ Equal(interface{ Equal(...) bool }) bool }) bool { return t == u.(T) }
换句话说,您最终会遇到递归
以下是我使用此技巧的更新代码-它有效-有人可能会发现此技巧很有用。
package eater type ProductServiceI interface { New() interface { Eat() } } type Eater struct { productService ProductServiceI } func New(productService ProductServiceI) *Eater { return &Eater{ productService: productService, } } func (a *Eater) EatUntilHappy() { for i:=0; i < 5; i++ { product := a.productService.New() product.Eat() } }
package main import "./apple/service" import "./eater" func main() { appleService := &service.AppleService{} appleEater := eater.New(appleService) appleEater.EatUntilHappy() }
package service import "./apple" type AppleService struct { } func (a *AppleService) New() interface{ Eat() } { return &apple.Apple{} }
结果:)
# go run main.go mniam, mniam mniam, mniam mniam, mniam mniam, mniam mniam, mniam