Recently I saw this:
Unfortunately, the Opaque interface isn't a private implementation at all. Anyone could come along and implement it themselves. But what if we modify our original interface definition to be this instead:
type Opaque interface { // Public
GetNumber() int // Public
implementsOpaque() // Private
}
Now we have a public interface, Opaque, but it contains a private method implementsOpaque. Within my package I am free to define implementsOpaque because it's visible, so I can make the internalBasicType conform to the Opaque interface with one line:
func (m *internalBasicType) implementsOpaque() {}
Now, whereas I don't agree with the conclusion of this blog, this notion of opaque interfaces intrigued me. I immediately thought of the ways another package might use the Opaque interface, and I considered embedding it. Why not embed Opaque in another interface type and simply implement the methods for the new one?
I went to the
language spec to see what it said about interface types and "lower-case" methods, and it is silent. In fact, what it says is wrong:
An interface may use an interface type name T in place of a method specification. The effect, called embedding an interface, is equivalent to enumerating the methods of T explicitly in the interface.
and this is exactly what does not happen. Although you can embed Opaque in another interface type definition, it is impossible to implement the new interface. I put Opaque in pkga and wrote this:
package pkgb
import "iftest/pkga"
type MyInterface interface {
pkga.Opaque
}
type OB int
func (OB) implementsOpaque() {}
func (OB) GetNumber() int { return 0 }
func TestAFunc() {
var x MyInterface
var y OB
x = y
}
and the compiler gives messages like:
# iftest/pkgb
./pkgb.go:17: cannot use y (type OB) as type MyInterface in assignment:
OB does not implement MyInterface (missing pkga.implementsOpaque method)
have implementsOpaque()
want pkga.implementsOpaque()
whereas implementsOpaque ought to be a method in interface MyInterface, just like GetNumber is.
Whether the spec should change or the compiler is a moot point, but something's gotta give.