15

I have code with interface:

package main

import (
    "math"
    "fmt"
)

type Circle struct {
    x, y, r float64
}

type Rectangle struct {
    x1, y1, x2, y2 float64
}

type Figure interface {
    Area() float64
}

func (c *Circle) Area() float64 {
    return math.Pi * c.r * c.r
}

func (r *Rectangle) Area() float64 {
    return math.Abs(r.x2 - r.x1) * math.Abs(r.y2 - r.y1)
}

func main() {
    figures := make([]Figure, 0)
    figures = append(figures, &Circle{0, 0, 10})
    figures = append(figures, &Rectangle{0, 0, 10, 20})
    for _, figure := range figures {
        fmt.Print(figure.Area(), "\n")
    }
}

output:

314.159265
200

and code with only methods for my struct:

package main

import (
    "math"
    "fmt"
)

type Circle struct {
    x, y, r float64
}

type Rectangle struct {
    x1, y1, x2, y2 float64
}

func (c *Circle) Area() float64 {
    return math.Pi * c.r * c.r
}

func (r *Rectangle) Area() float64 {
    return math.Abs(r.x2 - r.x1) * math.Abs(r.y2 - r.y1)
}

func main() {
    c := Circle{0,0,10}
    r := Rectangle{0,0,10,20}

    fmt.Print(c.Area(), "\n")
    fmt.Print(r.Area(), "\n")
}

and the same output:

314.1592653589793
200

When I use interface I have extra code in the form of interfaces declaration. If the interfaces perfectly implement polymorphism in Go, why then the methods of structures? What plus from interfaces, where is the difference? May be my example not good. Thank you!

rtut
  • 303
  • 1
  • 3
  • 18
  • 2
    You should see it in your own code: in the first case you could handle all in _unity_, as values of `Figure` and so you could store them in a slice, and range over them and call their `Area()` method. In the 2nd case without interfaces you did not store them in a slice and you did not use a loop, instead you had to call `Area()` manually on each instance. Possible duplicate of [Why are interfaces needed in Golang?](https://stackoverflow.com/questions/39092925/why-are-interfaces-needed-in-golang/39100038#39100038) – icza Apr 12 '18 at 13:16
  • i agree with: "so you could store them in a slice", but in both cases I describe two method Area. But thank you for you answer! – rtut Apr 12 '18 at 13:21
  • Why use an interface? Decouple code. See https://stackoverflow.com/a/62297796/12817546. Call a method “dynamically”. See https://stackoverflow.com/a/62336440/12817546. Access a Go package. See https://stackoverflow.com/a/62278078/12817546. Assign any value to a variable. See https://stackoverflow.com/a/62337836/12817546. –  Jul 10 '20 at 09:45

1 Answers1

20

You should see it in your own code: in the first case you could handle all in unity, as values of Figure and so you could store them in a slice (of type []Figure), and range over them and call their Area() method.

In the 2nd case without interfaces you did not store them in a slice and you did not use a loop, instead you had to call Area() manually on each instance.

Without interfaces there is no type for which to create a slice of and store each in it. The only option would be the interface{} type:

figures := make([]interface{}, 0)
figures = append(figures, &Circle{0, 0, 10})
figures = append(figures, &Rectangle{0, 0, 10, 20})

But then when ranging over them, you wouldn't be able to call their Area() method, as the interface{} type does not define any methods.

for _, figure := range figures {
    fmt.Print(figure.Area(), "\n") // COMPILE-TIME error
}

If you only have 2 instances, you can call their Area() methods manually, it would be even shorter. But if you have a hundred or a thousand...

Without repeating advantages of interfaces, see possible duplicate:
Why are interfaces needed in Golang?

icza
  • 389,944
  • 63
  • 907
  • 827