Maison  >  Article  >  développement back-end  >  Pourquoi Go génère-t-il une erreur lorsqu'une implémentation de type concret renvoie un type concret au lieu du type d'interface attendu dans une méthode d'interface ?

Pourquoi Go génère-t-il une erreur lorsqu'une implémentation de type concret renvoie un type concret au lieu du type d'interface attendu dans une méthode d'interface ?

DDD
DDDoriginal
2024-10-30 07:33:02187parcourir

Why does Go throw an error when a concrete type implementation returns a concrete type instead of the expected interface type in an interface method?

Méthode d'interface renvoyant une incompatibilité d'interface avec l'implémentation d'un type concret

Lorsque vous travaillez avec des interfaces Go, une erreur peut se produire lorsqu'une méthode d'interface qui déclare un type de retour d'interface est implémentée par un type concret. Cette erreur survient car l'implémentation de la méthode ne renvoie pas directement le type d'interface mais renvoie plutôt un type concret qui implémente l'interface.

Considérons l'exemple suivant :

<code class="go">package main

import "fmt"

type Foo struct {
    val string
}

func (f *Foo) String() string {
    return f.val
}

type StringerGetter interface {
    GetStringer() fmt.Stringer
}

type Bar struct{}

func (b *Bar) GetStringer() *Foo {
    return &Foo{"foo"}
}

func Printer(s StringerGetter) {
    fmt.Println(s.GetStringer())
}

func main() {
    f := Bar{}
    Printer(&f)
}</code>

Ici, le La fonction Printer attend une interface StringerGetter, qui possède une méthode GetStringer qui renvoie un fmt.Stringer, tandis que la méthode GetStringer du type Bar renvoie un type concret Foo qui implémente l'interface fmt.Stringer. Cela provoque l'erreur :

prog.go:29: cannot use &f (type *Bar) as type StringerGetter in
argument to Printer: *Bar does not implement StringerGetter (wrong
type for GetStringer method) had GetStringer() *Foo want
GetStringer() fmt.Stringer

La solution à ce problème réside dans le fait que les méthodes de l'interface correspondent aux types d'interface attendus. Dans ce cas, la méthode GetStringer doit renvoyer fmt.Stringer au lieu d'un type concret :

<code class="go">func (b *Bar) GetStringer() fmt.Stringer {
    return &Foo{"foo"}
}</code>

Alternativement, on peut créer un type wrapper qui implémente l'interface souhaitée et délègue au type concret, comme démontré dans les techniques suivantes :

Incorporation de types avec délégation:

<code class="go">type MyBar struct{ Bar }

func (b *MyBar) GetStringer() fmt.Stringer {
    return b.Bar.GetStringer()
}</code>

Encapsulage de types:

<code class="go">type MyBar Bar

func (b *MyBar) GetStringer() fmt.Stringer {
    return &Foo{"foo"}
}</code>

Ces techniques permettre une interface transparente avec les types de béton sans les modifier directement. En encapsulant ou en intégrant les types concrets, des types personnalisés peuvent être créés qui respectent les contrats d'interface souhaités.

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn