Home > database >  Improving Polymorphism and Decorator pattern in Go
Improving Polymorphism and Decorator pattern in Go

Time:08-31

I'm working through a design patterns book and trying to apply the patterns to Go as a way to learn both.

Currently I have reached the decorator pattern and I ran into a scenario I was curious about.

Here is some sample code:

type Beverage interface {
    getDescription() string
    cost() float64
}

type HouseBlend struct{}

func (hb *HouseBlend) getDescription() string {
    return "House Blend Coffee"
}

func (hb *HouseBlend) cost() float64 {
    return .89
}

type Mocha struct {
    b Beverage
}

func (m *Mocha) getDescription() string {
    return m.b.getDescription()   ", Mocha"
}

func (m *Mocha) cost() float64 {
    return m.b.cost()   .20
}

What is the difference between

var hb Beverage = &HouseBlend{}

//This works since hb is an interface type
hb = &Mocha{
    b: hb,
}

And

hb := &HouseBlend{}

//This assignment fails since Mocha is not type HouseBlend
hb = &Mocha{
    b: hb,
}

This also works

hb := *new(Beverage)

    hb = &Espresso{}

    hb = &Mocha{
        b: hb,
    }

Is there a shorthand way of giving my variable hb the interface type or does it need to be explicit in order to be able to "decorate" my struct and reassign the variable to different types?

Any suggestions on improving the decorator pattern here and achieving clean polymorphism are welcome. Thank you!

CodePudding user response:

var hb Beverage is how you explicitly give the variable a type. Implicit typing will always get the type of the value you put into it. I'm not sure what you're looking for in terms of "shorthand" here, as var name Type is already pretty short, but if you really want to use a short variable declaration you could use a type conversion:

hb := Beverage(&HouseBlend{})

CodePudding user response:

You can use the short form and declare hb as an interface using:

hb:=Beverage(&HouseBlend{})

This piece of code is not exactly correct:

// You allocate a pointer to an interface, and redirect it to get an uninitialized interface value
hb := *new(Beverage)

// Here, you throw away the value of the first assignment
hb = &Espresso{}
  • Related