method resolution order

133 views
Skip to first unread message

Stephan Lukits

unread,
Sep 16, 2020, 4:51:27 AM9/16/20
to golang-nuts
Assume a public interface I with two methods NotInS and M whereas NotInS
is calling M. An implementation i of I which implements NotInS and M as
well as a specialization s of i which only implements M. Finally a
constructor whose return-type is I returns a pointer to an instance of
s. Calling on this return-value NotInS will execute i.M() as the
following test shows. I would like it to call s.M(). How would I do
this in a goish way? Thanks for any help!

package main

import (
"fmt"
)

type I interface {
NotInS()
M()
}

type i struct{}

func (_i *i) NotInS() {
_i.M()
}

func (_i *i) M() {
fmt.Println("i")
}

type s struct{ *i }

func (_s *s) M() {
fmt.Println("s")
}

func newI() I {
return &s{&i{}}
}

func main() {
_i := newI()
_i.NotInS() // prints i instead of s
}

Volker Dobler

unread,
Sep 16, 2020, 5:13:05 AM9/16/20
to golang-nuts
On Wednesday, 16 September 2020 at 10:51:27 UTC+2 stephan...@gmail.com wrote:
Assume a public interface I with two methods NotInS and M whereas NotInS
is calling M. An implementation i of I which implements NotInS and M as
well as a specialization s of i which only implements M. Finally a
constructor whose return-type is I returns a pointer to an instance of
s. Calling on this return-value NotInS will execute i.M() as the
following test shows. I would like it to call s.M(). How would I do
this in a goish way? Thanks for any help!

Well, start of by not using Java/C#/C++ terminology as Go is different
and in Go you simply cannot have a "specialization s of i" as there are
no "specialization" as there is no inheritance. Also let's rewrite the code
to be a bit more  Go'ish:

     package main

     import "fmt"

     type I interface {
         NotInS()
         M()
     }

     type T struct{}
     func (t *T) NotInS() {  t.M()  }
     func (t *T) M() {  fmt.Println("T.M")  }

     type S struct{ *T }
     func (s *S) M() {  fmt.Println("S.M")  }

     func main() {
         x := &S{&T{}}
         x.NotInS() 
     }    

You see S has no method NotInS defined and all calls to
NotInS are automatically directed to implicit field T of
S. Remember that embedding a *T in an S has nothing to
do with inheritance or specialisation. It is just some tiny
syntactic sugar for an implicit field and automatic method
forwarding to that field. Spelling it out your code is
equivalent to:
     type S struct{ T *T }
     func (s *S) NotInS() { s.T.M()  }

The embedded T doesn't know it is a field of S and you
call T's M method and it is simply impossible to have
S's M method called like this.

You must redesign. Embedding is not  inheritance and
you cannot modle inheritance based design with embedding
no matter how hard you try.

V.
     

Axel Wagner

unread,
Sep 16, 2020, 5:20:27 AM9/16/20
to Stephan Lukits, golang-nuts
On Wed, Sep 16, 2020 at 10:51 AM Stephan Lukits <stephan...@gmail.com> wrote:
Assume a public interface I with two methods NotInS and M whereas NotInS
is calling M.  An implementation i of I which implements NotInS and M as
well as a specialization s of i which only implements M.  Finally a
constructor whose return-type is I returns a pointer to an instance of
s.  Calling on this return-value NotInS will execute i.M() as the
following test shows.  I would like it to call s.M(). How would I do
this in a goish way?

You can't. What you want is definitionally not "goish". Go doesn't have a way to "specialize" a type or overload methods. If you want a method of `*i` to call a method of another value, you need to pass that value to that `*i` somehow.

Your broader problem likely has a solution in Go, but you narrowed down the definition of what you want so far, that it's not achievable in Go.

 
  Thanks for any help!

package main

import (
        "fmt"
)

type I interface {
        NotInS()
        M()
}

type i struct{}

func (_i *i) NotInS() {
        _i.M()
}

func (_i *i) M() {
        fmt.Println("i")
}

type s struct{ *i }

func (_s *s) M() {
        fmt.Println("s")
}

func newI() I {
        return &s{&i{}}
}

func main() {
        _i := newI()
        _i.NotInS() // prints i instead of s
}

--
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...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/golang-nuts/fb4e1386-4c24-6486-58b3-93dd07e46259%40gmail.com.

Dan Kortschak

unread,
Sep 16, 2020, 5:24:11 AM9/16/20
to golang-nuts
Yes, it's sort of like asking what the best way to translate "This
sentence is not Spanish." into Spanish; you can do it, but it doesn't
make a lot of sense.
> --
> 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...@googlegroups.com.
> To view this discussion on the web visit
> https://groups.google.com/d/msgid/golang-nuts/27f6fcb8-2040-491a-8309-85629d02406bn%40googlegroups.com
> .


Stephan Lukits

unread,
Sep 16, 2020, 5:29:16 AM9/16/20
to golang-nuts
Thank you for your effort! It's not so much about terminology but more about avoiding duplicate code.
And a way to do that is abstraction and specialization (has not necessarly something to do with inheritance). 
So after your explanation I would then
- factor everything from NotInS which can be done on the abstraction level of T out
- implement NotInS as well in S utilizing the provided functionality of T and adding its own "specialication"
 

Reply all
Reply to author
Forward
0 new messages