Go embedded struct call child method instead parent method -
here sample of go code interface, parent struct , 2 children structs
package main import ( "fmt" "math" ) // shape interface : defines methods type shapeinterface interface { area() float64 getname() string printarea() } // shape struct : standard shape area equal 0.0 type shape struct { name string } func (s *shape) area() float64 { return 0.0 } func (s *shape) getname() string { return s.name } func (s *shape) printarea() { fmt.printf("%s : area %v\r\n", s.name, s.area()) } // rectangle struct : redefine area method type rectangle struct { shape w, h float64 } func (r *rectangle) area() float64 { return r.w * r.h } // circle struct : redefine area , printarea method type circle struct { shape r float64 } func (c *circle) area() float64 { return c.r * c.r * math.pi } func (c *circle) printarea() { fmt.printf("%s : area %v\r\n", c.getname(), c.area()) } // genreric printarea interface func printarea (s shapeinterface){ fmt.printf("interface => %s : area %v\r\n", s.getname(), s.area()) } //main instruction : 3 shapes of each type //store them in slice of shapeinterface //print each area call of 2 methods func main() { s := shape{name: "shape1"} c := circle{shape: shape{name: "circle1"}, r: 10} r := rectangle{shape: shape{name: "rectangle1"}, w: 5, h: 4} listshape := []c{&s, &c, &r} _, si := range listshape { si.printarea() //!! problem witch area method called !! printarea(si) } } i have results :
$ go run essai_interface_struct.go shape1 : area 0 interface => shape1 : area 0 circle1 : area 314.1592653589793 interface => circle1 : area 314.1592653589793 rectangle1 : area 0 interface => rectangle1 : area 20 my problem call of shape.printarea call shape.area method circle , rectangle instead calling circle.area , rectangle.area method.
is bug in go ?
thanks help.
actually in example calling shapeinterface.printarea() works fine in case of circle because created printarea() method type circle. since did not create printarea() rectangle type, method of embedded shape type called.
this not bug, intended working. go not (quite) object oriented language: not have classes , does not have type inheritance; supports similar construct called embedding both on struct level , on interface level, , have methods.
what expect called virtual methods: expect printarea() method call "overridden" area() method, in go there no inheritance , virtual methods.
the definition of shape.printarea() call shape.area() , happens. shape not know struct , if embedded in, can't "dispatch" method call virtual, run-time method.
the go language specification: selectors describe exact rules followed when evaluating x.f expression (where f may method) choose method called in end. key points:
- a selector
fmay denote field or methodfof typet, or may refer field or methodfof nested anonymous field oft. number of anonymous fields traversed reachfcalled depth int.- for value
xof typetor*ttnot pointer or interface type,x.fdenotes field or method @ shallowest depth intthere suchf.
going details
circle
in case of circle: si.printarea() call circle.printarea() because created such method:
func (c *circle) printarea() { fmt.printf("%s : area %v\r\n", c.getname(), c.area()) } in method c.area() called c *circle, method *circle receiver called exists.
printarea(si) calls si.area(). since si cicle , there method area() circle receiver, invoked no problem.
rectangle
in case of rectangle si.printarea() call method shape.printarea() because did not define printarea() method rectangle type (there no method receiver *rectangle). , implementation of shape.printarea() method calls shape.area() not rectangle.area() - discussed, shape doesn't know rectangle. you'll see
rectangle1 : area 0 printed instead of expected rectangle1 : area 20.
but if call printarea(si) (passing rectangle), calls si.area() rectangle.area() because such method exists.
Comments
Post a Comment