4 ms·
Real world example I hit a few weeks ago: I implemented a DB driver that had its own Next() method. Later I wanted to implement the SQL package interface. That
by rbetts 11y ago
Real world example I hit a few weeks ago:
I implemented a DB driver that had its own Next() method. Later I wanted to implement the SQL package interface. That interface contains Next() (http://golang.org/src/database/sql/sql.go?s=40568:40595#L1575 http://golang.org/src/database/sql/sql.go?s=40568:40595#L157...).
Choices - break backwards compatibility and change the interface I control or convolute the type definitions to create a type specific to the database/sql interface.
This limitation in combination with methods only being distinguished by name, not by parameters, turns out to be very annoying -- especially as interfaces profliferate.
- EugeneOZ 11y agoSecond option (separate interface) is obvious choice with duck-typing interfaces. edit: just to clarify: I don't like the idea "write more descriptive (over-verbose) method names" as solution for this problem.
- pcwalton 11y ago> Second option (separate interface) is obvious choice with duck-typing interfaces. And this is called the "adapter pattern" in Java. It's also very annoying to have to use it when you hit it.
- infogulch 11y agoThanks for the example. Out of curiosity, what was the signature of your Next method? > I implemented a DB driver that had its own Next() method. Later I wanted to implement the SQL package interface. (Did you mean the database/sql/driver driver.Rows interface[1]? sql.Rows is a struct not an interface.) Just to be clear, you implemented a DB driver and then went to satisfy the driver interface? And this was after you already published it and would break backwards compatibility? > especially as interfaces proliferate. True. There will only be more interfaces over time. We'll want to keep them as small and descriptive as possible if we want the ecosystem to be sustainable. [1]: https://golang.org/pkg/database/sql/driver/#Rows https://golang.org/pkg/database/sql/driver/#Rows
- NateDad 11y agoJust a copy and paste from the solution I posted elsewhere... this really shouldn't be too hard to work around: You can easily make a wrapper type that simply masks the underlying Next() method with its own implementation. type MyType struct {} func (m *MyType) Next(i int) { // do base next stuff } type ForSql struct { *MyType } func (f ForSql) Next() bool { // do sql-next stuff } and then using this type is trivial in-code: mt := &MyType{} doSomeSqlThing(ForSql{mt}) Note that this new type retains all the methods of the original type, so it still implements all the interfaces it used to (unless they rely on the old Next signature).