2017-01-29 3 views
-1

Правило is, методы могут быть определены только по именованному типу и указателю на именованный тип.GO - метод redeclared error


Для ниже code,

package main 

type Cat struct { 
} 

func (c Cat) foo() { 
    // do stuff_ 
} 

func (c *Cat) foo() { 
    // do stuff_ 
} 

func main() { 

} 

компилятор выдаст сообщение об ошибке:

main.go:10: method redeclared: Cat.foo 
    method(Cat) func() 
    method(*Cat) func() 

Приведенный выше код определяет,

метод foo() для имени типа (Cat) и

метода foo() для указателя с именем типа (*Cat).

Вопрос:

для GO компилятора, почему методы, определенные для различных типов считается же?

+0

С этой ошибкой, Как я знаю, какие методы должны быть определены для разрешенного типа? – overexchange

+1

Возможный дубликат [GO - Почему неявные методы не указателя не удовлетворяют интерфейсу?] (Http://stackoverflow.com/questions/41922181/go-why-implicit-non-pointer-methods-not-satisfy-interface) –

+0

@ dev.bmax, как вы думаете, что это дубликат? Если этот запрос получил ответ Эд, поделитесь им – overexchange

ответ

2

In Go, приемники - это своего рода синтаксический сахар. Фактическая, временная подпись функции (c Cat) foo() - foo(c Cat). Приемник перемещается в первый параметр.

Перейти не поддерживает перегрузку имени. В пакете может быть только одна функция с именем foo.

Сказав вышеприведенные утверждения, вы увидите, что будут две функции с именем foo с различными сигнатурами. Этот язык не поддерживает его.

Вы не можете сделать это в Го. Эмпирическое правило - написать метод для получателя указателя, и Go будет использовать его всякий раз, когда у вас есть указатель или значение.

Если вам все еще нужны два варианта, вам понадобятся названия методов по-разному.

+0

Функция 'foo()' имеет такую ​​же подпись. В методе '(Cat) foo()' & '(* Cat) foo()', первым параметром является параметр типа приемника, который создает различную подпись. Итак, как подписи одинаковы? компилятор не жалуется, что функция ('foo') имеет одну и ту же подпись – overexchange

+0

@overexchange Если у вас есть' var c Cat' и вызывается 'c.foo()', как вы можете устранить, какой метод следует вызывать? –

+0

@JonathonReinhart ** 1) ** Вы просите, если компилятор GO допускает оба метода, то, говоря: 'var c Cat; c.foo()', какой метод вызывать? тип приемника '(c Cat)', предположительно, должен быть неоднозначным. ** 2) ** Когда я говорю 'func (c * Cat) foo() {..}' метод определения ** для ** типа приемника ('* Cat'), но не для типа приемника (' Cat') и * наоборот * ** 3) ** С этой ошибкой, почему я должен знать, какой метод мне нужно определить 'func (c * Cat) foo() {..}' или 'func (c Cat) foo() {..} ', потому что метод foo имеет другую сигнатуру с первым параметром как один с именованным типом и второй в качестве указателя на именованный тип – overexchange

0

Например, вы можете моделировать некоторые кошачье поведение, как это:

package main 

import (
    "fmt" 
) 

type Growler interface{ 
    Growl() bool 
} 

type Cat struct{ 
    Name string 
    Age int 
} 

// *Cat is good for both objects and "object references" (pointers to objects) 
func (c *Cat) Speak() bool{ 
    fmt.Println("Meow!") 
    return true 
} 

func (c *Cat) Growl() bool{ 
    fmt.Println("Grrr!") 
    return true 
} 


func main() { 
    var felix Cat // is not a pointer 
    felix.Speak() // works :-) 
    felix.Growl() // works :-) 

    var ginger *Cat = new(Cat) 
    ginger.Speak() // works :-) 
    ginger.Growl() // works :-) 
}