Composite pattern

62 views
Skip to first unread message

Frank S

unread,
Feb 2, 2010, 11:32:57 PM2/2/10
to golang-nuts
I'm new to Go and come from a Java background. I'm trying to implement
the composite pattern.
A Directory can contain Nodes (Files and Directories). File and
Directory implement "Size() int" and "Name() string" and therefore the
Node interface. Have a look at the source:

//===========================
package composite

import "container/vector"

type Node interface {
Size() int
Name() string
}
//-----------------------
type File struct {
name string
size int
}

func NewFile(name string, size int) *File {
if (size < 0 || name == "") {
return nil
}
return &File{name:name, size:size}
}

func (file *File) Name() string {
return file.name
}

func (file *File) Size() int {
return file.size
}

//-----------------------
type Directory struct {
name string
children *vector.Vector
}

func NewDirectory (name string) *Directory {
if (name == "") {
return nil
}
return &Directory{name:name, children:new(vector.Vector)}
}

func (dir *Directory) Name() string {
return dir.name
}

func (dir *Directory) Size() int {
size := 0
for i := 0; i < dir.children.Len(); i++ {
node := dir.children.At(i).(*Node)
size += node.Size()
}
return size
}

func (dir *Directory) Add(node *Node) {
dir.children.Push(node)
}

//===========================
package main

import "composite"

func main() {
var dir = composite.NewDirectory("dir1")
var file = composite.NewFile("file1", 20)
dir.Add(file)
}

But if I try add a File object to Directory the compiler complains:
cannot use file (type *composite.File) as type *composite.Node in
function argument

I'd appreciate if someone could help me. How do I have to write the Add
() function in Directory to accept Files and Directories (or more
general everything that implements the Node interface)?

Thanks!
Frank

Ian Lance Taylor

unread,
Feb 2, 2010, 11:59:32 PM2/2/10
to Frank S, golang-nuts
Frank S <bo...@web.de> writes:

> func (dir *Directory) Size() int {
> size := 0
> for i := 0; i < dir.children.Len(); i++ {
> node := dir.children.At(i).(*Node)
> size += node.Size()
> }
> return size
> }
>
> func (dir *Directory) Add(node *Node) {
> dir.children.Push(node)
> }

Node is an interface value. The type *File satisfies the interface
Node. So if your function has a parameter of type Node, you can pass
an argument of type *File.

You've written your function with a parameter of *Node, which is not
an interface--it's a pointer to an interface. You can only pass an
argument of type *Node.

Similarly, once you push a Node, in Add, you will want to pull out a
Node, not a *Node, in Size.

Ian

Frank S

unread,
Feb 3, 2010, 12:22:41 AM2/3/10
to golang-nuts
That did the trick.
Darn pointers. As I said, Java background. Took me a while to figure
out when to use pointers and where something is passed by value...
Some day I'll get my head around it. I understand the idea, but it is
not second nature yet. Thanks a lot.
Reply all
Reply to author
Forward
0 new messages