Signification d’une structure avec interface anonyme intégrée?

paquet de sort :

 type Interface interface { Len() int Less(i, j int) bool Swap(i, j int) } ... type reverse struct { Interface } 

Quelle est la signification de l’interface anonyme Interface in struct reverse ?

De cette manière, reverse implémente le sort.Interface et nous pouvons remplacer une méthode spécifique sans avoir à définir tous les autres

 type reverse struct { // This embedded Interface permits Reverse to use the methods of // another Interface implementation. Interface } 

Remarquez comment il échange (j,i) au lieu de (i,j) et c’est aussi la seule méthode déclarée pour la structure reverse même si reverse outil reverse sort.Interface

 // Less returns the opposite of the embedded implementation's Less method. func (r reverse) Less(i, j int) bool { return r.Interface.Less(j, i) } 

Quelle que soit la structure passée dans cette méthode, nous la convertissons en une nouvelle structure reverse .

 // Reverse returns the reverse order for data. func Reverse(data Interface) Interface { return &reverse{data} } 

La vraie valeur vient si vous pensez ce que vous devriez faire si cette approche n’était pas possible.

  1. Ajouter une autre méthode Reverse au sort.Interface ?
  2. Créer une autre ReverseInterface?
  3. …?

Toute modification nécessiterait beaucoup plus de lignes de code sur des milliers de packages qui souhaitent utiliser la fonctionnalité inversée standard.

Ok, la réponse acceptée m’a aidé à comprendre, mais j’ai décidé de poster une explication qui me semble convenir mieux à ma façon de penser.

Le “Effective Go” a des exemples d’interfaces ayant incorporé d’autres interfaces:

 // ReadWriter is the interface that combines the Reader and Writer interfaces. type ReadWriter interface { Reader Writer } 

et une structure ayant d’autres structures incorporées:

 // ReadWriter stores pointers to a Reader and a Writer. // It implements io.ReadWriter. type ReadWriter struct { *Reader // *bufio.Reader *Writer // *bufio.Writer } 

Mais il n’y a aucune mention d’une structure ayant une interface intégrée. J’étais confus en voyant cela dans le paquet de sort :

 type Interface interface { Len() int Less(i, j int) bool Swap(i, j int) } ... type reverse struct { Interface } 

Mais l’idée est simple. C’est presque la même chose que:

 type reverse struct { IntSlice // IntSlice struct attaches the methods of Interface to []int, sorting in increasing order } 

les méthodes de IntSlice sont promues à reverse .

Et ça:

 type reverse struct { Interface } 

signifie que sort.reverse peut incorporer n’importe quelle structure qui implémente l’interface sort.Interface et quelles que soient les méthodes de cette interface, elles seront promues pour être reverse .

sort.Interface a la méthode Less(i, j int) bool qui peut maintenant être remplacée:

 // Less returns the opposite of the embedded implementation's Less method. func (r reverse) Less(i, j int) bool { return r.Interface.Less(j, i) } 

Ma confusion dans la compréhension

 type reverse struct { Interface } 

était que je pensais qu’une structure a toujours une structure fixe, c’est-à-dire un nombre fixe de champs de types fixes.

Mais ce qui suit me prouve le contraire:

 package main import "fmt" // some interface type Ssortingnger interface { Ssortingng() ssortingng } // a struct that implements Ssortingnger interface type Struct1 struct { field1 ssortingng } func (s Struct1) Ssortingng() ssortingng { return s.field1 } // another struct that implements Ssortingnger interface, but has a different set of fields type Struct2 struct { field1 []ssortingng dummy bool } func (s Struct2) Ssortingng() ssortingng { return fmt.Sprintf("%v, %v", s.field1, s.dummy) } // container that can embedd any struct which implements Ssortingnger interface type SsortingngerContainer struct { Ssortingnger } func main() { // the following prints: This is Struct1 fmt.Println(SsortingngerContainer{Struct1{"This is Struct1"}}) // the following prints: [This is Struct1], true fmt.Println(SsortingngerContainer{Struct2{[]ssortingng{"This", "is", "Struct1"}, true}}) // the following does not comstack: // cannot use "This is a type that does not implement Ssortingnger" (type ssortingng) // as type Ssortingnger in field value: // ssortingng does not implement Ssortingnger (missing Ssortingng method) fmt.Println(SsortingngerContainer{"This is a type that does not implement Ssortingnger"}) } 

La déclaration

 type reverse struct { Interface } 

vous permet d’initialiser l’ reverse avec tout ce qui implémente l’interface Interface . Exemple:

 &reverse{sort.Intslice([]int{1,2,3})} 

De cette façon, toutes les méthodes implémentées par la valeur de l’ Interface intégrée sont remplies à l’extérieur alors que vous pouvez toujours en remplacer certaines, par exemple Less pour inverser le sorting.

C’est ce qui se passe réellement lorsque vous utilisez sort.Reverse . Vous pouvez lire sur l’intégration dans la section struct de la spécification .

Je vais aussi donner mon explication. Le paquet de sort définit un type non exporté, qui est une structure, qui incorpore l’ Interface .

 type reverse struct { // This embedded Interface permits Reverse to use the methods of // another Interface implementation. Interface } 

Cela permet à Reverse d’utiliser les méthodes d’une autre implémentation d’Interface. C’est la composition dite, qui est une fonctionnalité puissante de Go.

La méthode Less pour reverse appelle la méthode Less de la valeur de l’ Interface intégrée, mais avec les index inversés, en inversant l’ordre des résultats du sorting.

 // Less returns the opposite of the embedded implementation's Less method. func (r reverse) Less(i, j int) bool { return r.Interface.Less(j, i) } 

Len et Swap les deux autres méthodes d’ reverse , sont implicitement fournis par la valeur de l’ Interface origine car il s’agit d’un champ incorporé. La fonction Reverse exscope renvoie une instance du type reverse qui contient la valeur Interface origine.

 // Reverse returns the reverse order for data. func Reverse(data Interface) Interface { return &reverse{data} }