[Go] Methods and Interfaces その1

### Method
A method is a function with a special receiver argument.

type Vertex struct {
	X, Y float64
}

func (v Vertex) Abs() float64 {
	return math.Sqrt(v.X*v.X + v.Y*v.Y)
}

func main(){
	v := Vertex{3, 4}
	fmt.Println(v.Abs())
}

– Methods are functions
You can declare a method on non-struct types, too.

type MyFloat float64

func (f MyFloat) Abs() float64 {
	if f < 0 {
		return float64(-f)
	}
	return float64(f)
}

func main(){
	f := MyFloat(-math.Sqrt2)
	fmt.Println(f.Abs())
}

– Pointer receivers
You can declare methods with pointer receivers.

type Vertex struct {
	X, Y float64
}

func (v Vertex) Abs() float64 {
	return math.Sqrt(v.X*v.X + v.Y*v.Y)
}

func (v *Vertex) Scale(f float64){
	v.X = v.X * f
	v.Y = v.Y * f
}

func main(){
	v := Vertex{3, 4}
	v.Scale(10)
	fmt.Println(v.Abs())
}

### Interface
An interface type is defined as a set of method signatures

type Abser interface {
	Abs() float64
}

func main(){
	var a Abser
	f := MyFloat(-math.Sqrt2)
	v := Vertex{3, 4}

	a = f
	a = &v

	a = v

	fmt.Println(a.Abs())
}

type MyFloat float64

func(f MyFloat) Abs() float64 {
	if f < 0 {
		return float64(-f)
	}
	return float64(f)
}

type Vertex struct {
	X, Y float64
}

func(v *Vertex) Abs() float64 {
	return math.Sqrt(v.X*v.X + v.Y*v.Y)
}

# command-line-arguments
./hello.go:19:4: cannot use v (type Vertex) as type Abser in assignment:
Vertex does not implement Abser (Abs method has pointer receiver)

– Interfaces are implemented implicitly
A type implements an interface by implementing its methods. There is no explicit declaration of intent, no “implements” keyword.

type I interface {
	M()
}

type T struct {
	S string
}

func (t T) M(){
	fmt.Println(t.S)
}

func main(){
	var i I = T{"hello"}
	i.M()
}

– Interface values
Under the hood, interface values can be thought of as a tuple of value and a concrete type.

type I interface {
	M()
}

type T struct {
	S string
}

func (t *T) M(){
	fmt.Println(t.S)
}

type F float64

func(f F) M(){
	fmt.Println(f)
}

func main(){
	var i I
	i = &T{"hello"}
	describe(i)
	i.M()

	i = F(math.Pi)
	describe(i)
	i.M()
}

func describe(i I){
	fmt.Printf("(%v, %T)\n", i, i)
}

interfaceやったなあ