Я много размышлял об этой конкретной проблеме, и у меня возникло то, как я должен решить ее самым чистым способом.
Представьте себе приложение, похожее на это:
type AreaCalculator interface {
Area() int
}
type Rectangle struct {
color string
width int
height int
}
type (r *Rectangle) Area() int {
return r.width * r.height
}
type Circle struct {
color string
diameter int
}
type (c *Circle) Area() int {
return r.diameter / 2 * r.diameter / 2 * π
}
type Canvas struct {
children []AreaCalculator
}
func (c *Canvas) String() {
for child := range c.children {
fmt.Println("Area of child with color ", child.color, " ", child.Area())
}
}
Этот пример, очевидно, не будет компилироваться, потому что хотя метод String () Canvas может вызывать c.Area (), он не может получить доступc.color, поскольку нет способа убедиться, что структура, реализующая AreaCalculator, обладает этим свойством.
Одним из решений, которое я мог придумать, было сделать это следующим образом:
type AreaCalculator interface {
Area() int
Color() string
}
type Rectangle struct {
color string
width int
height int
}
type (r *Rectangle) Color() string {
return r.color
}
type (r *Rectangle) Area() int {
return r.width * r.height
}
type Circle struct {
color string
diameter int
}
type (c *Circle) Area() int {
return r.diameter / 2 * r.diameter / 2 * π
}
type (c *Circle) Color() string {
return c.color
}
type Canvas struct {
children []AreaCalculator
}
func (c *Canvas) String() {
for child := range c.children {
fmt.Println("Area of child with color ", child.Color(), " ", child.Area())
}
}
Другим способом было бы попробовать что-то вроде этого:
type Shape struct {
Area func() int
color string
diameter int
width int
height int
}
func NewCircle() Shape {
// Shape initialisation to represent a Circle. Setting Area func here
}
func NewRectangle() Shape {
// Shape initialisation to represent a Rectangle. Setting Area func here
}
type Canvas struct {
children []Shape
}
func (c *Canvas) String() {
for child := range c.children {
fmt.Println("Area of child with color", child.color, " ", child.Area())
}
}
Ни одно изэти варианты кажутся мне чистыми.Я уверен, что есть более чистое решение, о котором я не могу думать.