4 ms·
Whenever I look through golangs specs, I always get stuck on the same question. Why are the methods we define restricted to the types we define? I'm SURE there
by GhotiFish 14y ago
Whenever I look through golangs specs, I always get stuck on the same question.
Why are the methods we define restricted to the types we define? I'm SURE there is a good reason.
Others have said that it's because if you did allow that kind of thing to happen, you might get naming collisions in packages. I don't buy this argument, you could get naming collisions anyway from packages, Go resolves those issues by aliasing. Go also allows for polymorphic behavior by packaging the actual type of the method caller with its actual value, so resolving which method to use isn't any more complicated.
I don't get it, I'm sure there's a good reason! I just hope it's a good enough reason to throw out the kind of freedom that would allow you.
- Jabbles 14y agoYou can't add methods to a type in a different package as you might break that package. By locking the method set of types when a package is compiled you provide some guarantee of what it does, and it doesn't need to get recompiled again! This is central to Go's ideals of compiling fast. Besides, embedding a type is very easy http://golang.org/ref/spec#Struct_types http://golang.org/ref/spec#Struct_types
- GhotiFish 14y agoHmmm. I can see how adding methods to a type in a different package would require that package to be recompiled, but I don't see how I could break that package. Unless there's some reflection magic I'm not considering. I'm reading through the embedded types now. I am new to golang so this one is lost on me. I thought if you wanted your own methods on a type from another package, you just aliased it with your own type def. though it looks like there's some kinda prototyping behavior being described here? If S contains an anonymous field T, the method sets of S and *S both include promoted methods with receiver T. The method set of *S also includes promoted methods with receiver *T. If S contains an anonymous field *T, the method sets of S and *S both include promoted methods with receiver T or *T.
- Jabbles 14y agoFor example, if you do a runtime type assertion to see if a variable satisfies an interface: v, ok := x.(T) http://golang.org/ref/spec#Type_assertions http://golang.org/ref/spec#Type_assertions If you "monkey-patch" x to satisfy T in another package, the value of ok may change.
- GhotiFish 14y agoHmm I can kind of see what you mean, but I don't see it as a big of a problem. If you make package A depend on package B, package B monkey-patches x with method Foo so now x is a Fooer x now satisfies the Fooer interface in package A, well that seems ok. You imported B after all. In things that don't import B, x doesn't satisfy Fooer. Is this unexpected behavior? If B depends on C, C's x won't satisfy Fooer right?
- pcwalton 14y agoBecause if you had package A that defined type T, package B that defined method Foo on T and, separately, package C that defined method Foo on T, then B and C could not be linked together.
- GhotiFish 14y agoI don't see why, personally, B defines Foo on T, so whenever B uses Foo, it should use B's Foo. C defines Foo on T, so whenever C uses Foo, it should use C's Foo. why is it ambiguous for the compiler which one to use?
- pcwalton 14y agoIf package D linked against B and C and called Foo(), which Foo() would it call?
- GhotiFish 14y agoGood question. If package B defined the function Bar(), and package C defined the function Bar(), then if package D linked to packages B and C, which function should it call when it asks for Bar()? Naming collisions are a solved problem.
- pcwalton 14y agoYou don't have to import methods in Go; the compiler just finds them. They're in a per-type namespace and therefore would be vulnerable to collisions. Of course, they could change the language to allow/require you to import methods, but that would add some complexity. On the other hand, you have to import functions, so your example isn't a problem.
- mseepgood 14y agoIn Go each external function call is preceded by its package name to avoid collisions, but you don't have packages within the method namespace of a type.
- enneff 14y agoIt's because Go was designed for large code bases, and doing what you describe leads to unmaintainable code. You might be interested in this document: http://talks.golang.org/2012/splash.article http://talks.golang.org/2012/splash.article