-
Notifications
You must be signed in to change notification settings - Fork 17.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
spec: allow embedding overlapping interfaces #6977
Comments
Labels changed: added release-none, languagechange. Owner changed to @griesemer. |
Note that even if you factor out the common method into its own interface it doesn't work: type C interface { String() string } type CI interface { C; f() } type CJ interface { C; g() } type CIJ interface { CI; CJ } http://play.golang.org/p/r5yOykMn-a prog.go:8: duplicate method String |
Say struct SI implements I, struct SJ implements J, and struct SIJ implements IJ,
In this case, GO doesn't know which |
@geterns You're example is confusing and syntactically incorrect (did you mean SI := struct { I }, etc.?). Either way, the proposal is about overlapping interfaces and the resulting interface - structs are not related to this except that a struct may implement an interface. How that interface came to be is unrelated at that point. |
@griesemer Yes, I'm sorry about the mistask. My example is about combining interfaces with duplicate method(s) in a struct - by explictly implementing the common method(s) of interfaces for the struct, it works. However, combining interfaces with duplicate method(s) to get a new interface is still not working :( |
@geterns This is a long-term issue and a language change (although backward-compatible). It's unimportant (though not hard to implement) and thus likely won't be addressed anytime soon. Regarding your other comments about combining interfaces in a struct: embedding in structs is different from embedding in interfaces - conflicts are only reported if access is ambiguous in the struct case. |
I'd love to see this fixed. Interfaces is Go are pretty awesome and this is a fly in the ointment. I wonder what the original justification was for generating errors under these conditions? As long as the overlapping method signatures are identical I can't imagine why you'd ever want the compiler to flag this as an error. |
FWIW, I just filed a dup (#15666) on behalf of a friend for whom this was causing considerable frustration. |
Perhaps we should try to address this for 1.8. It seems pretty straightforward and incontroversial. Anybody having good counter arguments why this might be a mistake? |
Just to explain how this comes up in real life: I tend to abstract away the data layer from the business layer so a) I can easy make mocks for tests, and b) I can have flexibility in changing data providers, sharding data, etc. Typical interface might be:
So then I have some other packages that want to be able to fetch accounts under some circumstances, so they say they require their Database to have all of user's Database methods:
Then, I have some package that needs both of those packages, and its Database interface looks like:
And then, kablooey: Duplicate method GetAccount(accountID uint64) (model.Account, error) |
Would be neat if this was fixed, since it seems straight forward and non controversial. I run into it regularly and have to resort to copy-pasting method signatures. |
I think it's OK but I find it all a bit confusing. The clarity of "no duplicates" is comforting. |
surely if two interfaces include the same sub-set of methods, that’s telling you there is a lower level 'thing' that should have its own interface, having this an error means smaller (flexible) interfaces, I’d have thought this was spot-on for Go, doesn't the problem come from inheritance thinking? |
Type-equivalence does not always mean semantic equivalence. There are plenty of interfaces with additional behavior requirements that the compiler is not aware of. In a perfect world, all behavior would be specified in the type system, but this is not the case. In a pretty good world, developers would register their interfaces through a common query system and immediately deprecate colliding interfaces for distinct interfaces. Maybe something like Hoogle for Go interfaces? Meanwhile, a mechanism for disambiguation would be nice. |
Something I thought of: what's the expected behavior when
|
It should be, yes: since the method sets are identical and the interface FooBarrer {
Foo()
Bar()
}
interface BarBagger {
Bar()
Bag()
}
interface FooBarBagger {
Foo()
Bar()
Bag()
} with interface FooBarrer {
Foo()
Bar()
}
interface BarBagger {
Bar()
Bag()
}
interface FooBarBagger {
FooBarrer
BarBagger
} |
No. The package combining the two interfaces is The maintainer of Specifically, the change to either interface would also break type I interface {
B.X
B.Y
M() someOtherType
} |
What about:
|
That specific example won't work, because the But putting that aside, the |
Ack. I don't understand Go modules well enough to know how to concisely write a test case that uses them directly, so I resorted to pseudocode.
This is my inclination as well. |
I've submitted b7d097a. As of master, cmd/compile applies these rules for overlapping interfaces:
|
No objections raised, so accepting. |
Already implemented, so closing. |
Change https://golang.org/cl/214240 mentions this issue: |
This is a language change for Go 1.14. Updates golang/go#6977 Change-Id: Ia8b8dc446c4dd700caccf59ca0444a380c49ba15 Reviewed-on: https://go-review.googlesource.com/c/gofrontend/+/214240 Reviewed-by: Than McIntosh <[email protected]>
This is a language change for Go 1.14. Updates golang/go#6977 Reviewed-on: https://go-review.googlesource.com/c/gofrontend/+/214240 git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@280109 138bc75d-0d04-0410-961f-82ee72b054a4
This is a language change for Go 1.14. Updates golang/go#6977 Reviewed-on: https://go-review.googlesource.com/c/gofrontend/+/214240 From-SVN: r280109
Change https://golang.org/cl/216997 mentions this issue: |
…tes) Updates #6977. Updates #36878. Change-Id: I40594be85ee0a0d4b35bacc90104568d2b8a4761 Reviewed-on: https://go-review.googlesource.com/c/go/+/216997 Reviewed-by: Ian Lance Taylor <[email protected]>
Change https://golang.org/cl/217134 mentions this issue: |
Implementation changes in go/types for #6977 required that internal LookupFieldOrMethod calls had access to the current *Checker. In order to make quick progress, I added a *Checker receiver to the function LookupFieldOrMethod (thus making it a method), and added a new function LookupFieldOrMethod. The plan was always to rename that function (Checker.LookupFieldOrMethod) such that it wouldn't be exported; with the obvious name being Checker.lookupFieldOrMethod. But that name was already in use which is why I postponed the rename. Eventually I forgot to clean it up. This CL fixes that with the following renames: Checker.lookupFieldOrMethod => Checker.rawLookupFieldOrMethod Checker.LookupFieldOrMethod => Checker.lookupFieldOrMethod Updates #6977. Fixes #36916. Change-Id: Icfafd0de9a19841ba5bd87142730fe7323204491 Reviewed-on: https://go-review.googlesource.com/c/go/+/217134 Run-TryBot: Ian Lance Taylor <[email protected]> TryBot-Result: Gobot Gobot <[email protected]> Reviewed-by: Daniel Martí <[email protected]> Reviewed-by: Ian Lance Taylor <[email protected]>
The text was updated successfully, but these errors were encountered: