Interfaces After Qt
Qt taught me to appreciate explicit contracts. It also taught me that an object system can acquire enough machinery to qualify for municipal government.
Go’s interfaces are much smaller. A type satisfies an interface by having the required methods; it does not announce the relationship in its declaration. This took a moment to trust because I am used to inheritance lists serving as signposts.
Here is the complete contract for something that can write bytes in my current snapshot:
type Writer interface {
Write(p []byte) (n int, err os.Error)
}
A file can satisfy it. So can a network connection or a tiny test buffer. The producer only needs to accept a Writer:
func emit(w Writer, p []byte) os.Error {
_, err := w.Write(p)
return err
}
There is no implements Writer marker on those concrete types. The advantage is that I can define an interface around behavior already provided by a package. The package author did not need to predict my abstraction.
The cost is discoverability. Looking at a type alone does not list every interface it happens to satisfy, and a method signature changed by one type is a different method. Compiler diagnostics are doing more of the navigation work than they do in my C++ code.
I tried the idea on a log collector. The original Python version accepted anything with a write method because Python accepts almost anything until it does not. The Go version gets similar flexibility, but verifies the method set when values are connected. That is a useful middle ground.
Interfaces also contain a pair of things internally: a dynamic type and a dynamic value. An interface value can therefore be non-empty even when the pointer stored inside it is nil. I managed to manufacture that surprise within an hour, which must be some kind of efficiency record.
These details reflect a weekly build, not a stable release. Method-set and library conventions may still shift. Even so, structural satisfaction feels important. It encourages narrow contracts at the point of use rather than grand interface families designed before the program has done anything useful.