Thank you very much for taking the time to write the example code on the
playground. I understand how the inversion is supposed to happen and I
acknowledge it is very common in Go---to the extent that I think everyone
including myself would call your example idiomatic (and my VTable
attempt... let's just say it is heavily downvoted in Reddit :>).
I agree "is-a" can be bad, and my mentors have shown me many bad uses of it
over the years and I too avoid it by default. However, I also hope we can
agree that there may be some niche cases where "is-a" can be a reasonable
approach. In the toy example, squares and rectangles are shapes; in the
real-world examples that made me realize there may be a pattern to explore,
I was building some MVC projects and I see the "concrete descendant" models
are instantiations of the "semi-abstract base" model, the latter of which
handles all the common stuff including mutex acquisition and release in one
central place. While I cannot show you my MVC code, I assure you I was
building them essentially your way, project after project. I was just
curious if there may be another design that feels easier. (Again, I don't
make any claim about good performance here, but it feels adequate... Also,
I know that the VTable interface value takes two words and not just one and
so it is not as compact as I would wish.)
Having said the above, in your example, you have a (morally) `shape.Print`
function that takes an interface value of the intended "descendants" and
you expose their fields using interface methods. This is all very
idiomatic---no doubt. However, if there are 50 "base" fields similar to
shape.name, then a straightforward extension is to have each of the
descendants implement 50 methods to expose the fields. Of course, in this
case we may introduce an interface method that returns a struct of these
base fields. An alternative but hopefully still idiomatic solution would be
to bring back struct embedding and turn `shape.Print` into a method that
receives the base struct, and now the base fields in a descendant can be
accessed through the receiver. This was essentially how I ended up with the
"s.Print(s)" statement in the README. (I personally prefer the struct
embedding approach since the base is all in one place.)
I hope the above explanation is somewhat satisfactory in explaining my
motivation. I am not advocating we all use this VTable pattern in every
situation, and it certainly wasn't my intention to start a thread about
VTable. My question was about my wish to catch the "Buuuug" typo
Finally, may I ask what "go.mod" is? I didn't know I did that. Thanks!
On Monday, March 12, 2018 at 2:15:56 PM UTC-4, rog wrote:
> This is an interesting edge case that you've run across, and I've done
> similar things in the past but I don't buy your motivational example.
> Putting an embedded recursive reference to a value within the value
> itself seems to be asking for trouble to me.
> Go emphasises "has-a" relationships over "is-a" relationships, and
> ISTM that you're trying hard for the latter when the former provides a
> straightforward path to doing what you want.
> For example: https://play.golang.org/p/b2J05LxzGpT (stripped down to a
> single file so that it works in the Go playground).
> Specifically, by changing the Print function to a function from a
> method, we allow it to run on any value that implements the Shape
> interface without being a method on Shape itself. That is, Print *has
> a* Shape, rather than being part of a Shape.
> Does that not work for you?
You received this message because you are subscribed to the Google Groups
To unsubscribe from this group and stop receiving emails from it, send an email
For more options, visit https://groups.google.com/d/optout.