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.
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.)
"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...
I think it's because traditional OO models are more intuitive: People seem to innately understand that, for instance, squares and circles are both shapes; we're really, really good (too good, actually) at putting things into categories(1).
To really understand duck typing, you need to understand classical inheritance and also understand why it often sucks. Duck typing is much more abstract and harder to explain to people who haven't been bitten by deep, convoluted, incestuous inheritance trees.
(1) I think it's interesting that in Obj-c, categories are a way of injecting methods into an existing class, but if you think of the problem as a larger part of an ethereal or duck-typed system, the term 'category' makes a lot of sense: it's not an 'is-a' relationship it's a 'does-a': putting objects into buckets according to what they do (categories) seems like a more intuitive way to describe duck typing. 'you are what you eat' seems like a good starting point.
EDIT: while I'm sure the above paragraph doesn't seem mind-blowing to anyone who understands duck typing or 'categories', what i'm referring to is the terminology and the approach, I think that Obj-c may have briefly touched on a useful terminology for duck typing in general: the term 'categories', as way of thinking about duck typing, but the more general term for what I'm thinking as a 'category' is actually what Obj-c would refer to as a 'protocol'. I think if you flipped those terms, it might make more sense to people.
Do you honestly believe that people understand "This object of this subclass has all the methods of its superclass as well as all the methods of its class" better than "This object has all the methods of its declared interface type"?
Interfaces are simple: you can do X, Y, and Z to this object. Inheritance, abstract base classes, subclasses, superclasses, etc. are all much more complicated than interfaces.
You're right, humans are good at putting things into categories. So good, in fact, that practically nothing in the real world fits into one category. I'm not just a husband; I'm also a man and a programmer and a father and an American and a Californian and so on. These are all different ways to "interface" with me. To say that a single inheritance hierarchy is more intuitive than Go's interfaces is the object-oriented version of Stockholm syndrome: your vision has been so warped by so many years of C++/Java/Python OOP that you've forgotten how unintuitive it really is.
Duck typing is simple to understand. It's the natural way to understand objects. People have been doing it (kids have been doing it!) since Smalltalk in the 80s. You don't need to have "been bitten by deep, convoluted, incestuous inheritance trees" to understand or use duck typing. You don't even need to have been so traumatized to appreciate duck typing. Interfaces are simpler than inheritance and precede inheritance mentally: even most tutorial explanations of inheritance do so using the terminology of interfaces to explain how, why, and where you'll use inheritance.
IMHO you are conflating subtyping and subclassing.
The fact that something is a list carries an implicit knowledge that you can iterate it, even if the concepts of List and Iterable are just interfaces.
> I just call them static duck-typing, and then go on from there.
Duck typing is dynamically typed by definition. This is structural typing (http://en.wikipedia.org/wiki/Structural_typing) (named, sadly, OCaml allows anonymous structural types which is even neater)
> When people say "duck typing" they mean structural typing almost universally. You're not going to change them to use your terminology.
No, when people say "duck typing" they're talking about dynamically typed languages which blow up at runtime or perform runtime tests on existing property. That is duck-typing, it does not take in account things like parameters or return types and it doesn't blow up at parse time.
> Also, names are just shorthand in Go;
It's not a shorthand when you have to use them (I don't know if Go can infer structural types)
> No, when people say "duck typing" they're talking about dynamically typed languages
No, they're not. Explain OCaml's object system to any Ruby or Python programmer and they'll say, "Oh, it's duck typed?" Why do you think so many programmers (such as the one you "corrected" above) use the term "duck typing" for Go? Because they mean structural subtyping. Why do you think c2.com's wiki[0] gives OCaml and C++ template as examples of static duck typing? Because they are. Duck typing (like strong/weak typing) is entirely orthogonal to whether the typing is done statically or dynamically.
You don't have to use interface names in Go. Anywhere you type a name like "io.Reader" you can type the full "interface { ... }" declaration. It sounds like you're confusing type inference with nominal typing.
Honestly, I think I just don't understand it. When I call the method doThis() on some object implementing the interface Thingamabob, I am assured that it will do whatever Thingamabob::doThis() is obliged to do. Of course Thingamabob is short for a fully qualified name, there is no ambiguity here. And of course I am relying on whoever wrote the doThis() implementation obeying the contract of Thingamabob::doThis().
With duck-typing, how do I know that doThis() is actually an implementation of a (non-declared) interface? The chance for accidental clashes seems exceedingly high, the space of method names is not all that large. And what does it actually buy you?
The problem is you don't get compile time checking. If you forget that Foo implements IBar and change the method doSomething() so that it no longer implements IBar you only find out with runtime bugs.
I really like Go but it's been a while since I used it. Someone correct me if I'm wrong here.