|
The very point of an interface is to decouple the caller from all the implementation specifically because it will work differently between implementation. If you expect two classes to implement it the same way, you an abstract base, not an interface. Close is a particularly good example. One need only look at C#'s IDisposable to see that it does, in fact, work well. A mock might noop it, another class might close an FD, and yet another might make an RPC call. I agree that interfaces tend to have fairly narrow family tree. And, by this narrowness, there's little ambiguity about what T GetById(id int) means. As the tree expands, which happens with implicit interfaces, ambiguity is more likely. Nevertheless, there's a fairly large common vocabulary that we'd all largely agree on. Closer, Reader, Writer, Logger, etc. Even in more complex ones, I see little risk of confusion, say, http.ResponseWriter. And, something that I've noticed from Go (which I never did in C# or Java), is the tendency to favor very small interfaces, which ends up being pretty awesome. That aside, consider that implicit interfaces allow the consumer to define the interface. For example, you create a library that has a concrete struct called MyStruct with a method called DoStuff(). You define no interface because you don't need one. I, a consumer of your library, need an interface because in some cases I'm using your MyStruct to DoStuff and in other cases, I'm using my own implementation. So I create an interface, define DoStuff(), and BAM!, your structure now implements my interface. I don't have to change your code. Sure, the workaround is to wrap your structure in my own which implements the interface. But how, in this case, is the implicit interface not a huge win? Maybe, as you say, it'll screw over people who use it poorly. For everyone else, I see no drawbacks. |
Haskell's typeclasses work around this by letting you define "how a type implements an interface" at either the definition of the interface or the definition of the type. (Or, strictly, anywhere else both are in scope - but that gets messy for a few reasons, so it's discouraged and GHC warns about "orphan instances" unless you tell it not to.)