Go for Classic OO

From Adam Colton
Jump to navigation Jump to search

Key Difference

  • Private is package wide
  • structs are concrete, interfaces are abstract
  • interfaces ONLY specify methods
  • embedding
  • using funcs to customize behavior
  • methods can be defined on any type

The Basics

At first structs seem very classic-object (COB) like. A struct has fields and you can define methods on it. The first difference you'll notice though is that the methods are not in the struct.

Packages

It's also important to talk about the role packages play in Go-OO. Anything starting with an uppercase is public, lowercase is private. But unlike COO, privates are package wide.

Interfaces

Interfaces must match

one gotcha is that you may run into - interfaces must exactly match.

 Name() fmt.Stringer
 // does not match
 Name() someStringStruct

Use a lot

It's ok to use a lot of small interfaces. I have one project that deals with a complex graph with many node types. To keep it under control there are many different node interface types. Specifically, terminal nodes (no output), signals (no inputs), multiplexers (many inputs) and demultiplexers (many outputs) as well as nodes with a UI. And there was a core node type. Now a single node could fulfill several of these interfaces.

Types

Now it gets fun and weird. In Go, you can define a method on any local type except an interface. Yes, you can define a method on a function, you can sub-type an int and put methods on that. Anything.

Pointer Madness

A type and pointer to that type are not the same type. So Foo and *Foo are different types. This becomes important when fulfilling interfaces and there's one gotcha that can make it confusing.

Apparently this isn't true any more???? I'd like to find the change log.

Techniques

Staying DRY

Embedding Structs

This is one of the key uses of embedding.

Pluggable Method

Put a func field on the struct and have one of the methods wrap a call to that.

Sorter example

Pluggable Interface

Put an interface field on the struct and

Embed Interface

Embed an interface.

Privacy Tricks

Getters and Setters

Go does not have an explicit getter/setter pattern, but they are used frequently to access private fields.

Private abstract

Let's say you'll have 3 structs that will share some similarities, may just as simple as having a read-only ID. You can create a private struct with the necessary fields and embed that in the public structs. Externally, that struct is completely hidden, but the public methods and fields will be exposed.

Constructor Tricks

One of the things I found difficult after I started to understand GOO, was how to handle constructors. If an struct is public, users can bypass your constructor. But if it's not public, it can be very difficult for users to work with.

Constructor Check

Put a private, boolean "constructorOk" field on the object and have the constructor set this to true. Alternately, you can do this with "initilized" and then you don't even need to force the user to call the constructor.

Struct and Interface Pair

Make the struct private and create an interface for it that includes all the public methods. Have the constructor return the interface rather than the struct. This can get a little annoying because you may need to keep casting back. But you can add a private method to the interface that returns the underlying type. Now a user will be unable to implement the interface outside the package and you'll have an easy casting method.

Closing

So GOO is not COO.

Structs are a type that are a collection of fields. Any local, concrete type can serve as a method receiver. An interface defines a set of methods. Any type with those methods can be used to fulfill that interface.