You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I'm not sure if this is a good idea. But I have thought about it several times and would like to share it in case it has not been considered. This is for future versions of Go (probably Go 2.0).
Proposal
It would be nice if there is a way to define an interface type that is the method set of some arbitrary type T. My proposal is to simply generalize the existing interface embedding:
interface {
T
}
Currently T can only be an interface. The proposal is to allow other types as well, and the interface contains the method sets of all embedded types.
The same restrictions of struct embedding applies: T must not be a pointer type, and for non-interface type, *T can also be embeded.
The rules of interface embedding also applies: the method sets of embedded types must be disjoint.
Application
Suppose I need to write the following function that uses a concrete type someservice.Client:
funcMyFunc(*someservice.Client) {
// ....
}
To write unit test for MyFunc, I want to fake someservice.Client. An easy way is to change the above code to
Here myInterface contains a subset of the method set of *someservice.Client. However, if the method set is large, and if I need to change code back and forth (so it's hard to determine which methods are used), it would be tedious to keep myInterface up to date. The proposal will solve the problem:
typemyInterfaceinterface {
*someservice.Client
}
Note 1
A google search shows that people have written tools to generate interface from struct: https://github.com/vburenin/ifacemaker (not necessarily to solve the same problem I mentioned though).
Note2
Another note is that I think this can somewhat make "polymorphism" easier in Go. Struct embedding is like "inherence" in many ways, but not always. Suppose we have
typeDerivedstruct {
Base
}
We still need an interface type that contains the methods of Base if we want something that can hold either a Base or a Derived. And the proposed interface { Base } is such an interface.
The text was updated successfully, but these errors were encountered:
I think this proposal is symptomatic of a design flaw.
Interfaces should have a small number of methods as they describe behaviour, not identity. If an interface has a large set of methods then that is a clear sign of breaking the single responsibility principal.
An interface abstracts over behaviour, not types. It is common to see interfaces declared when there is only one implementation. Don’t do that.
Callers should define interfaces to declare the behaviour they expect. These interfaces should be smaller than the method set of implementations passed through those interfaces. That helps the caller declare precisely the behaviour it expects.
In summary, I think changing the language to make it easier to automatically generate interface definitions where the member methods are too numerous or too unstable is solving the wrong problem.
The only reason to have an interface type is to have multiple implementations. If the interface type is derived directly from one of the implementations, then any change to that implementation requires changing all the other implementations, or using them will fail. It seems a better methodology to start with the interface that does what you need, and write types that implement that. Or, in other words, the mechanism proposed here will encourage people to start with details of the implementation rather than the desired interface. It will also lead to unnecessary ties between types that are not related other than implementing the same interface.
I'm not sure if this is a good idea. But I have thought about it several times and would like to share it in case it has not been considered. This is for future versions of Go (probably Go 2.0).
Proposal
It would be nice if there is a way to define an interface type that is the method set of some arbitrary type
T
. My proposal is to simply generalize the existing interface embedding:Currently
T
can only be an interface. The proposal is to allow other types as well, and the interface contains the method sets of all embedded types.T
must not be a pointer type, and for non-interface type,*T
can also be embeded.Application
Suppose I need to write the following function that uses a concrete type
someservice.Client
:To write unit test for
MyFunc
, I want to fakesomeservice.Client
. An easy way is to change the above code toHere
myInterface
contains a subset of the method set of*someservice.Client
. However, if the method set is large, and if I need to change code back and forth (so it's hard to determine which methods are used), it would be tedious to keepmyInterface
up to date. The proposal will solve the problem:Note 1
A google search shows that people have written tools to generate interface from struct: https://github.com/vburenin/ifacemaker (not necessarily to solve the same problem I mentioned though).
Note2
Another note is that I think this can somewhat make "polymorphism" easier in Go. Struct embedding is like "inherence" in many ways, but not always. Suppose we have
We still need an interface type that contains the methods of
Base
if we want something that can hold either aBase
or aDerived
. And the proposedinterface { Base }
is such an interface.The text was updated successfully, but these errors were encountered: