Определяют ли получатели, какой метод применить? - PullRequest
0 голосов
/ 02 июля 2018

Тур по Го: https://tour.golang.org/methods/9

package main

import (
    "fmt"
    "math"
)

type Abser interface {
    Abs() float64
}

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

    a = f  // a MyFloat implements Abser
    a = &v // a *Vertex implements Abser

    // In the following line, v is a Vertex (not *Vertex)
    // and does NOT implement Abser.
    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)
}

В этом упражнении есть два Abs() метода. Но кажется, что строка 24, fmt.Println(a.Abs()), автоматически применяет ту, в которой есть получатель того же типа, что и переменная.

Это функция приемников?

1 Ответ

0 голосов
/ 02 июля 2018

Спецификация языка программирования Go

Наборы методов

Тип может иметь набор методов, связанный с ним. Набор методов Тип интерфейса - это его интерфейс. Набор методов любого другого типа T состоит из всех методов, объявленных с типом получателя T. Набор методов соответствующего типа указателя * T - множество всех методов объявляется с получателем * T или T (то есть, он также содержит метод набор T). Дополнительные правила применяются к структурам, содержащим встроенные поля, как описано в разделе о типах структуры. Любой другой тип имеет пустой набор методов. В наборе методов каждый метод должен иметь уникальный непустое имя метода.

Набор методов типа определяет интерфейсы, которые тип реализует и методы, которые могут быть вызваны с использованием приемника этого тип.


Набор методов типа определяет интерфейсы, которые тип реализует и методы, которые могут быть вызваны с использованием приемника этого тип.

Например, упрощение примера Go Tour,

package main

import (
    "fmt"
    "math"
)

type Abser interface {
    Abs() float64
}

type Vertex struct {
    X, Y float64
}

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

func main() {
    var a Abser
    a = &Vertex{3, 4} // a *Vertex implements Abser
    fmt.Println(a.Abs())
}

Детская площадка: https://play.golang.org/p/cf3WMcBI0WJ

Выход:

5

Переменная a типа Abser может содержать любой тип переменной, для которого установлен метод Abser: Abs() float64. Переменная a содержит *Vertex, который удовлетворяет Abser с набором методов func (v *Vertex) Abs() float64. Выражение a.Abs() выполняет метод Abs() для типа *Vertex, который в данный момент содержится.

...