Meaning of a struct with embedded anonymous interface?

后端 未结 5 1668
感动是毒
感动是毒 2020-12-07 08:42

sort package:

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

...

type reverse struct {
    Interface
}
         


        
5条回答
  •  悲哀的现实
    2020-12-07 08:57

    Ok, the accepted answer helped me understand, but I decided to post an explanation which I think suits better my way of thinking.

    The "Effective Go" has example of interfaces having embedded other interfaces:

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

    and a struct having embedded other structs:

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

    But there is no mention of a struct having embedded an interface. I was confused seeing this in sort package:

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

    But the idea is simple. It's almost the same as:

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

    methods of IntSlice being promoted to reverse.

    And this:

    type reverse struct {
        Interface
    }
    

    means that sort.reverse can embed any struct that implements interface sort.Interface and whatever methods that interface has, they will be promoted to reverse.

    sort.Interface has method Less(i, j int) bool which now can be overridden:

    // 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)
    }
    

    My confusion in understanding

    type reverse struct {
        Interface
    }
    

    was that I thought that a struct always has fixed structure, i.e. fixed number of fields of fixed types.

    But the following proves me wrong:

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

提交回复
热议问题