Hi Rog, 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 statically. :) Finally, may I ask what "go.mod" is? I didn't know I did that. Thanks! Maverick 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? > > cheers, > rog. > -- You received this message because you are subscribed to the Google Groups "golang-nuts" group. To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.