Up to Main Index Up to Journal for May, 2012 JOURNAL FOR SUNDAY 13TH MAY, 2012 ______________________________________________________________________________ SUBJECT: Embedding interfaces & structs - Part 1 DATE: Sun May 13 22:17:32 BST 2012 Quite a busy weekend, however I did manage to think alot about WolfMUD and how to structure and implement things. One good thing about having other stuff to do - you can walk away from a problem and just think for a while and idle over some ideas. Even managed to sit down at a keyboard and try a few of the ideas out. Expanding from Friday's musings the interface naming does not really work well: type Examinable interface { Examine() } type Edible interface { Eat() } type Gettable interface { Get() } Why is this? Well if you put each into it's own package you end up stuttering a lot: examinable.Examinable edible.Edible gettable.Gettable So, looking through the Go sources for inspiration, using 'Interface' as the name of the interfaces works much better: examinable.Interface edible.Interface gettable.Interface Also when composing things by embedding a lot you don't necessarily need to include all of the interfaces you are embedding. You only need to define the specific interface details applicable to what you are defining. Consider my reimplemented Thing: package thing type Interface interface { Name() string Description() string } type Thing struct { name string description string } func (t *Thing) Name() string { return t.name } func (t *Thing) Description() string { return t.description } func New(name, description string) *Thing { return &Thing{ name: name, description: description, } } This defines a basic thing from which other objects can be composed. Next we define an examinable object which embeds Thing: package examinable import ( "fmt" "thing" ) type Interface interface { Examine() } type Examinable struct { *thing.Thing } func (e *Examinable) Examine() { fmt.Printf("You examine %s. %s\n", e.Name(), e.Description()) } func New(name, description string) *Examinable { return Embed(thing.New(name, description)) } func Embed(thing *thing.Thing) *Examinable { return &Examinable{Thing: thing} } Notice the interface definition - we only specify Examine() and do not have to embed thing.Interface. Why is this? Well we do embed the thing struct. Interfaces only define behaviour. So an Examinable has Name() and Description() pulled in through the struct embedding and as it implements Name() and Description() it satisfies the thing.Interface automatically. What would happen if we did embed the thing interface? Our interface would have specified that an examinable MUST provide Name(), Description() and Examine() to be an Examinable. However it only actually needs to implement Examine(). There is also another oddity of embedding which is why we have the examinable.Embed() function, but I'll leave that for 'Embedding Part 2' as this is already quite long. -- Diddymus Up to Main Index Up to Journal for May, 2012