Why two named interfaces with same methods are treated as different ones - and how can you avoid that?
So let's say we have a guy who likes to eat products (Eater). He doesn't care what products he it, he only wants to be pointed out from where he can fetch new products. In other words he wants product service, but doesn't care what products product service will produce. In concrete implementation we will try to feed him with apples, so we will provide him with appleService.
Here is the result:
./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
Interfaces service.AppleI
and eater.AppleI
have same method Eat()
and nothing else but golang considers them as different ones. Why and how to avoid that? According to duck typing this should work because what actually ProductServiceI
requires is that provided struct has Eat()
method - it shouldn't care about what name has interface (service.ProductI
vs eater.ProductI
).
Below is full code:
==> ./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")
}
I thought it doesn't matter what name or what import path has interface as long as declaration is the same.