2016-06-30 9 views
4

Ich habe folgendes:Golang Methode außer Kraft setzen

type Base struct { 

} 

func(base *Base) Get() string { 
    return "base" 
} 

func(base *Base) GetName() string { 
    return base.Get() 
} 

Ich möchte einen neuen Typ mit einer neuen Implementierung von Get() definieren, so dass ich den neuen Typ anstelle von Base verwenden können und wo GetName() heißt es ruft die neue Get() Implementierung auf. Wenn ich Java benutze, würde ich Base erben und Get() außer Kraft setzen. Wie soll ich das in Go erreichen? Ich möchte Änderungen möglichst vermeiden, damit bestehende Base-Kunden nicht geändert werden müssen.

Mein erster Stich an das sieht aus wie ..

type Sub struct { 
    Base 
} 

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

..welche nicht funktioniert. Mein Gehirn ist noch nicht klar für Go.

+2

Mögliche Duplikat von [ Ist es möglich, eine überschriebene Methode von einer übergeordneten Struktur in golang aufzurufen?] (http: // stacko verflow.com/questions/21251242/is-it-possible-to-call-overridden-method-from-parent-struct-in-golang) – Vadyus

+1

Go hat keine Vererbung, noch hat es Generika. Wenn etwas den Typ 'Base' erwartet, können Sie das nicht mit einem anderen Typ angeben. – JimB

Antwort

2

Go ist keine "klassische" OO-Sprache: Sie kennt das Konzept von Klassen und Vererbung nicht.

Es enthält jedoch das sehr flexible Konzept der Schnittstellen, mit denen viele Aspekte der Objektorientierung zur Verfügung gestellt werden können. Schnittstellen in Go bieten eine Möglichkeit, das Verhalten eines Objekts zu spezifizieren: Wenn etwas das kann, dann kann es hier verwendet werden.

Eine Schnittstelle definiert eine Reihe von Methoden, aber diese Methoden enthalten keinen Code: Sie sind nicht implementiert (dh sie sind abstrakt).

So wie Sie erreichen können, verschiedene Typen innerhalb der gleichen Methode zu verwenden, verwenden Sie Schnittstellen. Hier

ist einfaches Beispiel zu beweisen es:

package main 

import (
    "fmt" 
) 

type Base struct{} 
type Baser interface { 
    Get() float32 
} 

type TypeOne struct { 
    value float32 
    Base 
} 

type TypeTwo struct { 
    value float32 
    Base 
} 

type TypeThree struct { 
    value float32 
    Base 
} 

func (t *TypeOne) Get() float32 { 
    return t.value 
} 

func (t *TypeTwo) Get() float32 { 
    return t.value * t.value 
} 

func (t *TypeThree) Get() float32 { 
    return t.value + t.value 
} 

func main() { 
    base := Base{} 
    t1 := &TypeOne{1, base} 
    t2 := &TypeTwo{2, base} 
    t3 := &TypeThree{4, base} 

    bases := []Baser{Baser(t1), Baser(t2), Baser(t3)} 

    for s, _ := range bases { 
     switch bases[s].(type) { 
     case *TypeOne: 
      fmt.Println("TypeOne") 
     case *TypeTwo: 
      fmt.Println("TypeTwo") 
     case *TypeThree: 
      fmt.Println("TypeThree") 
     } 

     fmt.Printf("The value is: %f\n", bases[s].Get()) 
    } 
} 

Go Playground

+5

Ich glaube nicht, dass dies die Frage beantwortet. Er wollte die Unterklasse instantiieren, GetName aufrufen und die Unterklassenmethode tatsächlich aufrufen lassen. Dieses Beispiel macht keinen Versuch, das anzugehen. –

1

Interfaces sind Sammlungen von Methodensignaturen genannt:
siehe: https://gobyexample.com/interfaces
und: http://www.golangbootcamp.com/book/interfaces
so ist es besser, nicht zu Verwenden Sie auf solche Weise OOP.


was fragen Sie ist golang nicht idiomatischen aber möglich (2 Möglichkeiten):

das ist, was Sie brauchen (Arbeitsbeispielcode):

package main 

import "fmt" 

type Base struct { 
} 

func (base *Base) Get() string { 
    return "base" 
} 

type Getter interface { 
    Get() string 
} 

func (base *Base) GetName(getter Getter) string { 
    if g, ok := getter.(Getter); ok { 
     return g.Get() 
    } else { 
     return base.Get() 
    } 
} 

// user code : 
type Sub struct { 
    Base 
} 

func (t *Sub) Get() string { 
    return "Sub" 
} 
func (t *Sub) GetName() string { 
    return t.Base.GetName(t) 
} 

func main() { 
    userType := Sub{} 
    fmt.Println(userType.GetName()) // user string 
} 

Ausgabe:

Wie Sie sehen, muss im Benutzercode ein Initialisierungscode eingegeben werden:

func (t *Sub) GetName() string { 
    return t.Base.GetName(t) 
} 

auch dies funktioniert:

package main 

import "fmt" 

type Getter interface { 
    Get() string 
} 

type Base struct { 
    Getter 
} 

func (base *Base) Get() string { 
    return "base" 
} 

func (base *Base) GetName() string { 
    return base.Getter.Get() 
} 

// user code : 
type Sub struct { 
    Base 
} 

func (t *Sub) Get() string { 
    return "Sub" 
} 
func New() *Sub { 
    userType := &Sub{} 
    userType.Getter = interface{}(userType).(Getter) 
    return userType 
} 

func main() { 
    userType := New() 
    fmt.Println(userType.GetName()) // user string 
} 

Ausgang:

wie Sie sehen eine Initialisierung Code muss in Benutzercode erfolgen:

userType.Getter = interface{}(userType).(Getter)