DEV Community

loading...

Discussion on: The Problem with Interfaces, and how Go Fixed it

Collapse
danielhoffmann_ profile image
Daniel HB

What about name collisions? This seems so wrong to me, how is type-safety enforced?

Collapse
thatjoemoore profile image
Joseph Moore

The Go developers believe that, with interfaces, you mostly care about what something can do, not what something is. So, instead of having a rigid type system with inheritance and all that mess, they allow functions and methods to just declare "I need something that can do these things." If you're coming from a more complex type system, like Java (which is where I came from), it can take some getting used to, but it's really one of my favorite parts of Go. It lets me concentrate on what things need to be doing, not what crazy class tree they're part of.

Collapse
danielhoffmann_ profile image
Daniel HB

I also come from Java world. I can see what you mean, but still what is the problem of just saying that this class implements this interface? This is completely unrelated to inheritance.

Thread Thread
dean profile image
Dean Bassett Author

Because declaring what an object is requires that you know that something exists.
Take that salad example from earlier: even though salads can be eaten, because it doesn't know the Edible interface exists, it isn't "Edible"
In Go, because Salad has an "Eat()" method, it can do everything that an Edible can do, so it is considered Edible.

Thread Thread
danielhoffmann_ profile image
Daniel HB

Well, I stopped to think about this a little more and I don't think I ever used 2 interfaces with the same method names in any of my code ever (although I have not been coding type-safe languages for a while now). I can see why go went this route, but it is hard to measure how many problems this might cause without making a large-scale project.

I still like the idea of specifying in the class what interfaces it implements, for example if a class implements Serializable I know ALL methods of Serializable are implemented there. Instead of having to check all the methods in a class, I can just check the class stub. This very useful when browsing the javadocs, I can just check the class implemented interfaces and see if it implements Serializable and just throw it at a JSON encoder or some other IO operation.

Thread Thread
dean profile image
Dean Bassett Author

It doesn't cause problems from my experience. Also interfaces in Go still require a full method signature. But in Go, interfaces shouldn't be used to define what a type is, but rather what it does. To tell what a type is, you can use GoDoc.

Collapse
coreload profile image
📶

A type that implements an interface does so solely by using a value of that type in a position for that interfaces. So a use is a kind of implicit definition.

If a type is used in the position of two interfaces with some or all method signatures in common this should be 1. suspect or 2. based on informal contracts that those common methods are intended to conform to each other. Type safety will be enforced. Intent should be suspect.

Collapse
danielhoffmann_ profile image
Daniel HB

Interesting, so there is some type inference going on when you throw an object at a method that expects an Interface as an argument. Thanks for the explanation!

Thread Thread
kunde21 profile image
Chad Kunde

In the case of passing a struct into a function that takes an interface, the compiler enforces interface requirements. It will even tell you what methods are missing from the type which cause it not to fulfill the interface.

Collapse
dean profile image
Dean Bassett Author

I re-read your question and realized that no one really answered it. I didn't want to get into the whole concept of packages in Go in the blog post so I didn't go into it. Basically, when referring to a type, variable, or anything, you refer to it through packagename.whatever. Our Edible interface could be referred to as mypackage.Edible, the Burger struct could be referred to as mypackage.Burger, although we can just refer to them as Edible and Burger because they are in our package.

Meanwhile, the Salad struct must be referred to as theirpackage.Salad because it is in a different package.

Also, in terms of type collisions with method names, all arguments and the return type must match the interface's in order for it to be considered "implemented".