2015-11-18 5 views
4
package main 

import "fmt" 

type Super struct{} 

func (super *Super) name() string { 
    return "Super" 
} 

func (super *Super) WhoAmI() { 
    fmt.Printf("I'm %s.\n", super.name()) 
} 

type Sub struct { 
    Super 
} 

func (sub *Sub) name() string { 
    return "Sub" 
} 

func main() { 
    sub := &Sub{Super{}} 
    sub.WhoAmI() 
} 

Я хочу получить «Я Суб», но вместо этого я получаю «Я супер».Как вызвать дочерний метод в родительском методе?

Я уже знаю sub.WhoAmI будет называть sub.Super.WhoAmI, но я все еще хочу знать, есть ли способ получить «I'm Sub». В Python, когда я пишу следующий код:

class Super(object): 

    def name(self): 
     return "Super" 

    def WhoAmI(self): 
     print("I'm {name}".format(name=self.name())) 

class Sub(Super): 

    def name(self): 
     return "Sub" 


if __name__ == "__main__": 
    sub = Sub() 
    sub.WhoAmI() 

Я могу получить «Я подчинен».

ответ

7

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

Например, здесь (playground) является более естественным способом сделать это в Go:

package main 

import "fmt" 

type Namer interface { 
    Name() string 
} 

type Super struct{} 

func (sub *Super) Name() string { 
    return "Super" 
} 

type Sub struct{} 

func (sub *Sub) Name() string { 
    return "Sub" 
} 

func WhoAmI(namer Namer) { 
    fmt.Printf("I'm %s.\n", namer.Name()) 
} 

func main() { 
    sub := &Sub{} 
    WhoAmI(sub) 
} 

Вместо того, чтобы сосредоточиться на классы (которые Go не имеют), это сосредотачивается на интерфейсах. Дело не в том, что вещи , это вопрос, что они могут сделать. Это очень мощный подход к программированию, и на практике он часто гораздо более гибкий и менее подвержен ошибкам, чем абстракции наследования.

2

Подумайте о функциях в Go, как будто все они принадлежат одному пространству имен. У Go действительно нет классов, методов или наследования, поэтому то, что вы пытаетесь, никогда не будет работать так, как вы планируете.

Иными словами, когда вы определяете функцию следующим образом:

func (f *Foo) DoStuff() 

Вы можете себе это действительно определяется как:

func DoStuff(f *Foo) 

Таким образом, вы можете заметить, почему Go выбрал для вызова функции name на вашем Super struct-это была единственная сигнатура функции, которая соответствовала. (. Обратите внимание, что в вашей WhoAmI функции super определяется как super *Super так Go соответствует его с соответствующей функцией того же типа)

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

http://play.golang.org/p/8ELw-9e7Re

package main 

import "fmt" 

type Indentifier interface { 
    WhoAmI() string 
} 

type A struct{} 

func (a *A) WhoAmI() string { 
    return "A" 
} 

type B struct{} 

func (b *B) WhoAmI() string { 
    return "B" 
} 

func doSomething(x Indentifier) { 
    fmt.Println("x is a", x.WhoAmI()) 
} 

func main() { 
    doSomething(&A{}) 
    doSomething(&B{}) 
} 
Смежные вопросы