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.

Reply via email to