new to Go. I'm trying to write a test that involves mocking a couple of structs where one of the struct's functions returns an instance of the other struct. However I'm running into an issue that I can reproduce with the following code:
package main
type Machine1 interface {
Produce() Material1
}
type Machine2 interface {
Produce() Material2
}
type Material1 interface {
Use() error
}
type Material2 interface {
Use() error
}
type PencilMachine struct{}
func (pm *PencilMachine) Produce() Material1 {
return &Pencil{}
}
type Pencil struct{}
func (p *Pencil) Use() error {
return nil
}
func main() {
pm := new(PencilMachine)
var m1 Machine1
m1 = Machine1(pm)
var m2 Machine2
m2 = Machine2(m1)
_ = m2
}
Which gives the following error:
prog.go:38: cannot convert m1 (type Machine1) to type Machine2:
Machine1 does not implement Machine2 (wrong type for Produce method)
have Produce() Material1
want Produce() Material2
Notice how the Pencil struct implements both the Material1 and Material2 interfaces. However the return type of (pm *PencilMachine) Produce() is Material1 and not Material2. Curious why this doesn't work because anything that implements Material1 also implements Material2.
Thanks!
Think of interfaces more as contracts. They don't implicitly implement other interfaces simply due to the fact they don't implement anything directly.
and interfaces are satisfied by implementations. (hopefully that makes sense)
In your example, having simple "Material" that both meachine types create would work, as in this: https://play.golang.org/p/ZoYJog2Xri
package main
type Machine1 interface {
Produce() Material
}
type Machine2 interface {
Produce() Material
}
type Material interface {
Use() error
}
type PencilMachine struct{}
func (pm *PencilMachine) Produce() Material {
return &Pencil{}
}
type Pencil struct{}
func (p *Pencil) Use() error {
return nil
}
func main() {
pm := new(PencilMachine)
var m1 Machine1
m1 = Machine1(pm)
var m2 Machine2
m2 = Machine2(m1)
_ = m2
}
Its because your pencil machine doesn't implement the Machine2 interface. Here is the culprit:
func (pm *PencilMachine) Produce() Material1 {
return &Pencil{}
}
You see that although PencilMachine has the same function Produce
it does not return the same data type (Material1) therefor it implements Machine1 only. Machine2 requires a Produce
function to return Material2