
Rob Pike on Go interfaces - fogus
https://groups.google.com/group/golang-nuts/msg/8de71de10ea48f96
======
darklajid
I probably have a parsing problem here. Can you help me solve it?

Knowing not a lot about Go I followed the links and saw that interfaces are
'implemented' implicitly, the quacks like a duck way. If I fulfill the
contract of an interface I can be used as something of that interface. Cool.

But - what is Rob's comment now?

"It's always bothered me in OO languages that we can make Circle, Square, etc.
subclasses of Shape (say), but that's the one design decision we get to make.
What if we want to align those things along other axes (so to speak), like
topological genus or plant genus, if you're a landscaper? You might lose your
way or dig yourself into a hole with multiple inheritance." (goes on, imo down
the same route)

From what I can tell there's no issue here. Except for the requirement to be
explicit (implements Foo, Baz, Baz) instead of implicit (just add those
interfaces' methods on your type) the very same thing can archived in the
biggest (market share?) OO languages. Java? Check. C#? Check.

What exactly is leading to this final quote:

"Go's interfaces aren't a variant on Java or C# interfaces, they're much more.
They are a key to large-scale programming and adaptable, evolutionary design."

I'm honest here. I don't get it. Duck typing? Yeah, fine. I think I'd like
that. But what am I missing? It seems in Go you get two things: No need to
explicitly annotate the types with the classes it implements (good or bad,
probably depends on taste and general complexity of the code) and, perhaps
bigger?, you can probably extract interfaces later which are now magically
implemented. But both features seem to be ~refactoring/design~ details. Nifty
maybe, if they fit your style. But not a leap in any way?

~~~
apgwoz
Ok, so you're missing the main point. Suppose you have a library that isn't
yours, and you don't have the source code. But, it has a type "Foop" that
doesn't implement any of the interfaces you'd like it to for your purposes.
What do you do? In the Java world, you make a subclass and implement those
interfaces. We probably call that the Adapter pattern or something.

In the Go world, or the Haskell world, or even the Clojure world, we say, "No
problem. I'll just _extend_ Foop with this interface by adding these 3
methods."

Extending/adding those methods doesn't change Foop though. Foops are still
Foops and can still be used as is with the library that Foop was bundled with.
They just now implement a new interface for my purposes.

~~~
darklajid
Just to be sure: You suggest to write interfaces ('extract' in my original
post as that seems to be the refactoring name you'd use for this kind of stuff
in my world) that define a contract for pre-existing characteristics of 3rd
party types?

Or are you, as I read your sentence in quotes, talking about some kind of
monkey patching of the original classes?

I understand your point, but I don't understand the original post/mail.
Interfaces per se still seem to be the exact same thing, simple contracts, and
types can fulfill multiple of those. I guess my main problem is that for me
this is not a discussion about interfaces, this is a discussion about
orthogonal language features which might happen to allow you to use interfaces
a little more liberal.

That's why I started with my assumption of a parsing error: Reading the mail
I'd summarize that as 'Go interfaces are awesome and much better than C#/Java
equivalents' while the little amount of understanding I have right now lends
itself far better to 'Go interfaces are - well - just like any other
interfaces out there. But! We can weave them magically (java: AOP?) and
implicitly in at runtime'

Still a nice feat.

~~~
rapala
_"Just to be sure: You suggest to write interfaces ('extract' in my original
post as that seems to be the refactoring name you'd use for this kind of stuff
in my world) that define a contract for pre-existing characteristics of 3rd
party types?"_

No, in Go you can write new methods for pre-existing 3rd party types that you
do not have the source for. It has the feel of monkey patching, but there is
no classes in Go. A method is just a function that takes objects of certain
type as a parameter. Knowing an object's type does not tell you what actions
can be performed on it. To know that, you want to know what interfaces the
object implements.

This is a one way to solve the so called expression problem, which cannot be
solved by simple use of classes and interfaces in a language like Java.

------
jxcole
Go OO is like Java only they took stuff away. They took away class extension
and they took away the requirement that you declare interface implentations.
So if you have all of the functions required for an interface then you
implement the interface, no need to be more complicated.

So it's hard to see why people from an OO background (assuming an OO
background like Java or c++) would have a problem with it. It's like that only
simpler.

~~~
lukesandberg
I guess go interfaces are like c++ template implicit interfaces except the
interfaces have names instead of just protocols. I think the reason that it
can be difficult to grasp is because it isn't as explicit. Maybe OO
programmers are afraid of the crazy gcc error messages you get when you
incorrectly instantiate a template in c++ and think you might have the same
difficulty. Whereas explicit interface implementation declarations give you
better error reporting. I have very little go experience but when I first
learned about go interfaces that is where my mind went.

------
someone13
I've seen a lot of criticism of the choice to use interfaces in Go, but I
don't understand why. Can someone explain to me why some people seem to
dislike them? From my point of view, all they are is effectively the static
variant of duck-typing.

~~~
LeafStorm
That's pretty much exactly it. Duck-typing in dynamic languages is just "I
don't care what this _is_ as long as it doesn't break when I do stuff to it,"
and Go's interfaces are "I don't care what this _is_ as long as I can call
these methods on it." It's basically just a way to duck-type and guarantee
that the duck-typing will work at compile time.

I don't know why people dislike them, because the concept and the
possibilities involved are quite impressive. (Combined with generics, they
would be even more impressive...but that's another topic.)

~~~
colin_jack
"I don't know why people dislike them, because the concept and the
possibilities involved are quite impressive. (Combined with generics, they
would be even more impressive...but that's another topic.)"

Me neither, they seem great to me (same with optional typing in Dart). For me
the big advantage isn't going to be so much the compile-time checks, instead
its the documentation you get in the code from it (as in you can see that an
argument is a shape and quickly find out what you can do with a shape).

Have to say I've done no more than play with either language though so there
could be big real-world disadvantages that I'm missing...

------
eridius
The way Rob is describing this reminds me of Haskell's Typeclasses, of which
Go's interfaces are basically an ad-hoc informal version (sans default
implementations) without parametric polymorphism (but that's another topic
entirely).

~~~
quatrevingts
They're similar in that they both allow a type to be associated with a
supertype post-declaration, which is unusual in an OO language; they differ in
that Go uses structural subtyping rather than nominal subtyping which is much
more prevalent.

~~~
eridius
I had not heard the terms "structural subtyping" and "nominal subtyping"
before, so thank you for that (Wikipedia was able to define them). And yes, I
realize that Go's interfaces are implicit whereas Haskell's typeclasses are
explicit.

I was thinking more along the lines that Haskell's typeclasses provide the
exact same type of functionality that Rob is talking about wit Go's
Interfaces, e.g. a type Foo can be a TopologicalGenus and a GrassGenus and a
Square and an Area and a Symmetry all at the same time, by declaring the
appropriate typeclass interfaces.

They're also somewhat similar from a usage standpoint, where in both Haskell
and Go I can take a type Foo and declare methods on it that conform to a known
type Bar (e.g. declaring an interface Bar Foo in Haskell, or simply declaring
the methods from Bar in Go) and now my type Foo can be treated as that type
Bar even if I don't control the source to Foo.

------
akeefer
In general I like the way Go interfaces work (we'd like to do something
similar in Gosu as well); they let you decouple different parts of a system
much better than you can if you have to explicitly declare interfaces.

When discussing putting something like this in Gosu, the main disadvantage we
came up with was around tooling. Probably not a big issue for Go, given that I
haven't really heard of too much focus on IDE/refactoring tooling there, but
if one were to implement such tools, the implicit interfaces make things a bit
harder. For example, if I have a Nameable interface with a getName() method,
and 20 classes in my system have a getName() method but only 3 of them are
actually used as Nameables, if I want to refactor the getName() method in a
system like Java, I'll know which classes explicitly implement Nameable and
thus which classes to refactor. In Go, it's a hard problem, because you have
to know which classes are ever used as Nameables; that's no longer a property
of the class itself, but rather something you have to derive from your code
base. It similarly makes IDE functions like "find usages" or "find
implementors" much harder to implement. (Technically they're not 100%
intractable, but they're certainly much harder to do well.)

Those tooling issues are really the only drawbacks we could come up with,
though. Otherwise I think the Go approach is much more flexible than the Java
one.

~~~
rat87
wouldn't a bigger problem be that getName() may refer to getting a Person 's
name or an enumeration of the platform or worse. ie. that you use the same
names for unrelated functions which can happen and does make a certain amount
of sense sometimes.

~~~
akeefer
It's certainly a related problem: with Go-style implicit interfaces, neither a
person nor a machine really has the context to know if something that conforms
to the interface is actually intended to be used that way, or if it just
happens to have the same method signatures. As you say, getName() is a pretty
common sort of method name that could mean a bunch of different things, and
not everything with a getName() method is necessarily interchangeable with
everything else. Explicit interfaces require more work by the programmer, but
make those intentions explicit to both other programmers and to automated
tools.

In Gosu, we already have Java-style explicit interfaces, but we're likely
going to add in Go-style implicit interfaces as a language option as well,
since they're not completely interchangeable. The more I think about it, the
more I think that you often want implicit interfaces for method arguments, and
explicit interfaces for return values. That's oversimplifying, but as a
library author you often want to say "this method works with anything that has
foo() and bar() on it," so you want an implicit interface so people can use
your library with existing code without changing that code to add explicit
interface declarations. But if you're providing objects back as the result of
a function, you might want to be more explicit and make harder guarantees
about exactly what sorts of things they return.

------
ggchappell
> Moreover, you don't have to work them all out ahead of time; the whole
> design can evolve without invalidating early decisions.

That is a _very_ important point IMHO. In my experience, the Achilles heel of
classical C++/Java-style OO is that you tend to lock yourself into a
complicated design that is difficult to modify. This goes a long way toward
accounting for the recent-ish surge in popularity of dynamic languages, duck
typing, etc. Being able to apply a similar design mindset in a language with
static typing sounds pretty cool. (I've looked into Go a little; I think I'll
look into it some more.)

------
abstractfactory
Structural subtyping is not OO? Somewhere Luca Cardelli is scratching his
head.

~~~
azernik
Maybe Go interfaces fit a theoretical formulation of OO, but this isn't the OO
most people learned for Java or C++.

------
davvid
Go is a truly beautiful language; it really feels like a modern C. I hack
Python and C++ for a living but would much rather hack go.

