Calling overridden methods indirectly

2,180 views
Skip to first unread message

trialcodr

unread,
Mar 18, 2012, 2:26:23 PM3/18/12
to golang-nuts
Any idea why this code calls A.Foo() even though Bar() is called on a
value of type B?

package main

import (
"fmt"
)

type A struct {
}

func (a *A) Foo() {
fmt.Println("A.Foo()")
}

func (a *A) Bar() {
a.Foo()
}

type B struct {
A
}

func (b *B) Foo() {
fmt.Println("B.Foo()")
}

func main() {
b := B{A: A{}}
b.Bar()
}

Rémy Oudompheng

unread,
Mar 18, 2012, 6:55:19 PM3/18/12
to trialcodr, golang-nuts
Le 18 mars 2012 19:26, trialcodr <tria...@gmail.com> a écrit :
> Any idea why this code calls A.Foo() even though Bar() is called on a
> value of type B?

I'd say it's similar to why this code prints "Hello":

#include <cstdio>

class Hello {
public:
void print() { std::printf("Hello\n"); }
void action() { print(); }
};

class World: public Hello {
public:
void print() { std::printf("World\n"); }
};

int main() {
World w;
w.action();
return 0;
}

trialcodr

unread,
Mar 18, 2012, 7:18:59 PM3/18/12
to golan...@googlegroups.com, trialcodr
But if you declare print() as virtual it prints "World\n".
What's the point of emulating inheritance without virtual dispatch?

Volker Dobler

unread,
Mar 18, 2012, 8:13:02 PM3/18/12
to golang-nuts

On Mar 19, 12:18 am, trialcodr <trialc...@gmail.com> wrote:
> But if you declare print() as virtual it prints "World\n".
> What's the point of emulating inheritance without virtual dispatch?

Anonymous fields might be better thought of as composition than
as inheritance as I understand them. Composition with less typing
due to the promotion of fields and methods.

Volker

Steve McCoy

unread,
Mar 18, 2012, 8:38:53 PM3/18/12
to golan...@googlegroups.com, trialcodr
It isn't inheritance, so there isn't virtual dispatch. In main, b.Bar() is a shorthand for b.A.Bar(), and only a pointer to b's A member is passed into the method. There's no VMT-style lookup possible from this pointer; only interfaces have access to that kind of runtime dispatch.

trialcodr

unread,
Mar 19, 2012, 3:43:18 AM3/19/12
to golan...@googlegroups.com, trialcodr
Ok, thanks.
runtime dispatch = interface seems to be the way to Go.


package main

import (
    "fmt"
)

type I interface {
    Foo()
}

type A struct {
    i I

}

func (a *A) Foo() {
    fmt.Println("A.Foo()")
}

func (a *A) Bar() {
    a.i.Foo()

}

type B struct {
    A
}

func (b *B) Foo() {
    fmt.Println("B.Foo()")
}

func main() {
    b := B{A: A{}}
    b.i = &b
    b.Bar()

John Asmuth

unread,
Mar 19, 2012, 8:34:56 AM3/19/12
to golan...@googlegroups.com, trialcodr
If you design your code around inheritance-style polymorphism (which you do since that's the way people do it with java and C++), you're going to find go very awkward indeed.

Fortunately you do *not* need to design your code like that. Never once, since I got over my initial shock (I was a java/C++ dev) while writing a real Go program (which I have been doing since Go's initial announcement) have I ever found that inheritance-style polymorphism was the best approach to my problem.

Sure, you can make examples with Foos and Bars and Squares and Rectangles all day long, but those are trivial examples meant to show a *way* to do something, rather than a something to *do*.

- John

trialcodr

unread,
Mar 19, 2012, 11:22:23 AM3/19/12
to golan...@googlegroups.com, trialcodr
Ok, I'll bite.
How do you treat a list of values of different types in a uniform way without using polymorphism/interfaces in Go?

chris dollin

unread,
Mar 19, 2012, 11:28:46 AM3/19/12
to trialcodr, golan...@googlegroups.com
On 19 March 2012 15:22, trialcodr <tria...@gmail.com> wrote:
Ok, I'll bite.
How do you treat a list of values of different types in a uniform way without using polymorphism/interfaces in Go?

You wouldn't. You'd use interfaces: that's how Go handles
polymorphism.

Chris

--
Chris "allusive" Dollin

wan...@126.com

unread,
Nov 27, 2013, 7:45:16 AM11/27/13
to golan...@googlegroups.com, trialcodr
hi , even though without "    b.i = &b" , the code still works;
then I want to when i is initialized;
also
 a:=A{}
a.Bar(); //still works as want; it is strange; where is the guide that says code can be written in this way;


在 2012年3月19日星期一UTC+8下午3时43分18秒,trialcodr写道:

zhao...@gmail.com

unread,
Jan 20, 2014, 5:04:37 PM1/20/14
to golan...@googlegroups.com, trialcodr, wan...@126.com
if implement like this,following code will encounter a compile error, because a.i in nil
a := A{}
a.Bar()

在 2013年11月27日星期三UTC+8下午8时45分16秒,wan...@126.com写道:

Bienlein

unread,
Jan 21, 2014, 4:49:35 AM1/21/14
to golan...@googlegroups.com
The problem is well described in this article. See the in chapter "Inheritance" the sample with Magic() and MoreMagic(). A possible workaround is decribed in this blog (see chapter "Inner Pattern").

xingtao zhao

unread,
Jan 21, 2014, 8:51:04 PM1/21/14
to golan...@googlegroups.com
I think the "right go" way looks like this: http://play.golang.org/p/ecWmQdd9I7

C Banning

unread,
Jan 22, 2014, 7:31:16 AM1/22/14
to golan...@googlegroups.com

DV

unread,
Jan 22, 2014, 12:16:35 PM1/22/14
to golan...@googlegroups.com
C Banning has it right. 
In Go, you write a *function* (not a method, function) that takes an interface as a parameter. Boom, polymorphism. 
For an example in the std lib (one of hundreds, possibly) look at fmt.Printf. It's a package-level, free-standing function. Notice its first parameter - an io.Writer - an interface type. That's how it's done. 

Trying to code Go if your only way of thinking is "Java" will be about as successful as coding Haskell like you code C. 
Different languages have different patterns and idioms. 

DV

unread,
Jan 22, 2014, 12:18:22 PM1/22/14
to golan...@googlegroups.com
Gah. I meant fmt.Fprintf for my specific example. Although fmt.Printf works just as well as an example, I suppose. 

xingtao zhao

unread,
Jan 22, 2014, 4:51:00 PM1/22/14
to golan...@googlegroups.com
Yes, it is right when there is only one such function. But when there are many such functions, I think the wrapper style will be better. For example, matrix.Interface just implement any functions that will be overridden by different matrix types, and we leave the common functions on all matrix types to Matrix:

type Interface {
    Size() (r, c int)
    At(r, c int) float64
    Set(r, c int, v float64)
}

type Matrix {
    Interface
}

func (m Matrix) Add(n Matrix) Matrix { ... }
func (m Matrix) Mult(s float64) Matrix { ... }
...

In this case, it will convenient to define functions on Matrix and expose Matrix to public, instead of a list of independent functions that accept Interface.

While in the traditional OOP (java, c++), we would define a basic Matrix class with the virtual functions, and some common functions, and the subclasses will override the virtual functions of basic Matrix. While in Go, we can do it by the way above.

C Banning

unread,
Jan 23, 2014, 10:18:36 AM1/23/14
to golan...@googlegroups.com
Reply all
Reply to author
Forward
0 new messages