The interfaces portion of Golang CodeReviewComments states:
Go interfaces generally belong in the package that uses values of the interface type, not the package that implements those values. The implementing package should return concrete (usually pointer or struct) types: that way, new methods can be added to implementations without requiring extensive refactoring.
Yet, Go's context.go module both defines the Context interface and implements it for type emptyCtx int and type cancelCtx struct.
Note, the portion listed above says they "generally" belong in the package that uses values of the interface type — so I understand that this is not a strict rule.
However, I am curious as to what the criteria is that makes it OK for them to do this in the context package.
Also, this assumes CodeReviewComments is a canonical resource for Go code reviews and style guide.
Defining implementations of an interface in the same package is actually pretty common, especially when implementing a strategy pattern or chain of responsibility(like context).
Take the net package for example, it defines the Listener interface, but also TCPListener, UDPListener, and UnixListener. In this case it would be illogical to place the functionality in another package.
The io package does a similar thing with the readers and writers.
Another handy pattern is to define a function alias for interfaces which only have 1 function. Like how HandlerFunc implements Handler, allowing users to cast closures as HandlerFunc so they don't have to define their own type, which is much more work.
I'm looking for a way to annotate methods to indicate that they match some specified functional interface, and how to specify that some parameter requiring a method reference only accepts methods with that annotation.
Motivation: I'm looking to be able to check that the signatures of the method matches the accepted functional interface at compile-time rather than at run-time, when the method is called with incorrect arguments. (None of the methods are private, and all are able to be marked as final with no undesired side-effects)
I have a signal produced from a module. I want to define a signal listener class in another module but whenever I want to subclass it from CIListener, it says it cannot make a new instance from my subclassed listener because the CIListener class is a pure virtual class (interface class). But I have re-declared or redefined all the pure virtual methods in my listener class. Instead when I user CListener class to subclass my listener it works! Do I have to subclass from CIListener?
I guess you believe that you have re-defined all pure methods, but in fact the compiler thinks otherwise. There are 7 pure virtual methods that should be implemented with the proper signatures. If you want to support only certain data types (as it is in most cases) I would suggest to implement (extend) the cListener as it is just a NOP implementation of the cIListener interface (with all its methods throwing a datatype not supported error). Be sure to see whether you indeed override the necessary methods. You may use the override C++ keyword in your method definition.
Where should I write phpDoc? Upon interface in interface file or upon class that implements the interface?
I am a bit sad that I can't write return types and types of params before param in methods. In PHP I have to do that in phpDoc, but where should I write this?
I would write the docblock in the interface. If there is something specific for some class, you could write docblock for it.
You can specify argument types, see http://php.net/manual/en/language.oop5.typehinting.php
From the Go documentation on method declarations:
The receiver type must be of the form T or *T where T is a type name. T is called the receiver base type or just base type. The base type must not be a pointer or interface type and must be declared in the same package as the method.
Can anyone give me some insight on why this might be? Are there any other (statically typed) languages that would allow this? I really want to define methods on an interface so I can treat any instance of a given interface type as another. For example (stealing the example from the Wikipedia article on the Template Method Pattern) if the following was valid:
type Game interface {
PlayOneGame(playersCount int)
}
type GameImplementation interface {
InitializeGame()
MakePlay(player int)
EndOfGame() bool
PrintWinner()
}
func (game *GameImplementation) PlayOneGame(playersCount int) {
game.InitializeGame()
for j := 0; !game.EndOfGame(); j = (j + 1) % playersCount {
game.MakePlay(j)
}
game.PrintWinner()
}
I could use any instance implementing "GameImplementation" as a "Game" without any conversion:
var newGame Game
newGame = NewMonopolyGame() // implements GameImplementation
newGame.PlayOneGame(2)
UPDATE: the purpose of this was to try and achieve all the benefits of abstract base classes without all the coupling that goes with an explicit hierarchy. If I wanted to define a new behaviour PlayBestOfThreeGames, abstract base classes would require me to change the base class itself - whereas here I just define one more method on top of the GameImplementation interface
It's probably for the same reason you can't define methods on interfaces in Java.
An interface is meant to be a description of a part of, or the whole of, the external interface for a set of objects and not how they implement the underlying behavior. In Java you would probably use an abstract class if you need parts of the behavior to be pre-defined but I think the only way to do that in Go is to use functions rather than methods.
I believe that for your example the more Go idiomatic code would be something like this:
type GameImplementation interface {
InitializeGame()
MakePlay(player int)
EndOfGame() bool
PrintWinner()
}
func PlayOneGame(game GameImplementation, playersCount int) {
game.InitializeGame()
for j := 0; !game.EndOfGame(); j = (j + 1) % playersCount {
game.MakePlay(j)
}
game.PrintWinner()
}
Where PlayOneGame and any specific game implementation are probably living in different packages.
Here is some discussion on golang-nuts
In answer to your question of whether there are other statically typed languages that allow this: yes, most. Any language with multiple inheritance allows classes to have arbitrary mixes of abstract and concrete methods. Also, see Scala's traits, which are like Java's interfaces but can have concrete methods. Scala also has structural types, which are really all that Go's interfaces are.
What you're describing as in Interface is really what might elsewhere be referred to as an abstract class -- that is, a class with some methods defined but not all, which must be subclassed in order to be instantiated.
However, Go doesn't have any concept of a class hierarchy -- the whole type structure is flat. Each method on a class is defined for that class specifically, not on any parent class or subclass or interface. This was a conscious design decision, not an omission.
In Go, an Interface is therefore not a component of a type hierarchy (as there is no such thing). Instead, it is simply an ad-hoc specification of the set of methods which must be implemented for a given purpose. That's all. They're a stand-in for dynamic typing whereby you can declare ahead of time which functions on a given type you'll be using -- then any variable who's type satisfies those requirements can be used.
This makes it impossible to use patterns like Generics with Go, and Rob Pike has said at a conference that this might be changed in the future if someone can come with a an elegant implementation and a compelling use case. But that remains yet to be seen.
First, it's important to notice that types implement interfaces implicitly — that is, interfaces are "duck types". Any type that provides the methods required by the interface is assignable to a variable of the interface type, without any cooperation from the original type. This is different from, say, Java or C# where a class that implements an interface has to declare its intention to implement the interface, in addition to actually providing the methods.
Go also has a pretty strong tendency against "action at a distance". For example, even though methods are declared separately from types, it's illegal to declare a method in a different package from its receiver type. You can't just go adding methods to os.File.
If interfaces could provide methods (making them traits/roles) then any type that implemented an interface would gain a bunch of new methods out of nowhere. Someone reading the code and seeing those methods used probably have a hard time figuring out where they came from.
There's a problem with fragility — change the signature of a method that's required by an interface, and a bunch of other methods appear or disappear. In the case where they disappeared, it's not obvious where they "would have" come from. If types had to declare their intention to implement an interface then breaking the contract would prompt an error (and "accidentally" implementing an interface does nothing), but when interfaces are satisfied implicitly things are trickier.
Worse, there could be name conflicts — an interface provides a method with the same name as a method provided by a type that implements that interface, or two interfaces both provide a method with the same name, and some type happens to implement both of those interfaces. Resolving that conflict is the kind of complication that Go really likes to avoid, and in a lot of cases there is no satisfying resolution.
Basically, it would be really cool if interfaces could provide methods — roles as composable units of behavior are cool, and mesh well with Go's composition-over-inheritance philosophy — but actually doing it would be too complicated and too action-at-a-distance-y for Go to contemplate.