Search code examples
go

Access Interface Methods for Composed Class


I am working on code where I have a a collection of descriptions of various types. The different types of descriptions have common fields so using composition seems to make the best sense. Consider the following code:

type CompDescBaseType struct {
   Type string `json:"type"`
   Help string `json:"help"`
   HelpUrl string `json:"help_url"`
}

type CompDesc interface {
   GetHelp() string
}

func (c *CompDescBaseType) GetHelp(helpFiles map[string]string) string {
   rtn := c.Help
   if len(c.HelpUrl) > 0 {
      file, ok := helpFiles[c.HelpUrl]
      if ok {
         rtn = file
      }
   }
   return rtn
}

type CompDescIntType struct {
   CompDescBaseType
   MinValue int `json:"min"`
   MaxValue int `json:"max"`
}

func (c *CompDescIntType) GetHelp() string {
   // do I have to repeat the logic of CompDescBaseType here?
}

I know that, with golang, CompDescIntType is a different type and any methods declared for a different type have to be redeclared for the new type if both types are to conform to a declared interface. However, there is logic that can be solely implemented for the base type that I would rather not reproduce for any types that use composition with the base type. I would also like to avoid naming the composed struct as that will introduce redirection to any code that needs to access those contained fields including json.Marshall() and json.Unmarshall()

Is there any syntax that I can use to access the methods of a base structure within a method of a structure that composes that base?


Solution

  • You can easily use embedded fields to compose functionality:

    Given a struct type S and a named type T, promoted methods are included in the method set of the struct

    For example (Go Playground):

    type Hello struct{}
    
    func (Hello) Word1() string { return "Hello" }
    
    type World struct{}
    
    func (World) Word2() string { return "World" }
    
    type Composit struct {
        Hello
        World
    }
    
    func main() {
        var c Composit
    
        fmt.Println(c.Word1(), c.Word2())
    }