Faking type inheritance

39 views
Skip to first unread message

eadfrith

unread,
Dec 11, 2009, 2:12:06 PM12/11/09
to golang-nuts

As a Java programmer one of the things that threw me about Go was the
lack of type inheritance. However, I think the following is a
reasonable away to fake it:

type IA interface {
do2();
}

type A struct {
IA;
}

func (a *A) do1() {fmt.Print("A DO1 ");a.IA.do2()}
func (a *A) do2() {fmt.Println("A DO2")}

type B struct {
A;
}

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

func main() {
a := A{};
a.IA = &a;
a.do1();

b := B{};
b.IA = &b;
b.do1();
}

Output:

A DO1 A DO2
A DO1 B DO2

The thing I like about this is that the IA interface precisely defines
which methods a "subclass" is allowed to override. The thing I don't
like is the need to set IA upon construction, but this could be hidden
behind a factory method.

Now, whether type inheritance, even of the faked variety, is a
desirable thing is another matter. Also, apologies if this construct
is blindingly obvious to everyone else.

Santidhammo

unread,
Dec 11, 2009, 2:15:28 PM12/11/09
to golang-nuts
You can automate this by reflection and by factory methods. Factory
methods are the way in Go to initialize types.

Steven Blenkinsop

unread,
Dec 11, 2009, 2:40:58 PM12/11/09
to golang-nuts
On Dec 11, 2:15 pm, Santidhammo <svanle...@gmail.com> wrote:
> You can automate this by reflection and by factory methods.
How would you use reflection here?
I wouldn't call this faking inheritance. Its one of the many
constructs that the go system makes possible. I've seen this construct
floating around on here a bit, and came up with it independantly at
some point. Go lets you , by combining simple elements in simple ways,
define complex relationships that other languages would either
restrictively prescribe, or provide a dizzying multitude of special
case syntaxes to achieve (ehem D). By combining elements in different
ways you can create top down, bottom up, and looser relationships that
don't require stuffing things into a hierarchy. I think that makes Go
very powerful.

konrad

unread,
Dec 11, 2009, 4:27:05 PM12/11/09
to golang-nuts
The problem in the above is that when you call do2 the variable a
points to an instance of IA not to an instance of A. You only get the
component not the container. There is actually no way to get the
container back. Go Composition does not fake inheritance.

Yes it did work in the above trivial case but that is only beacuse it
is trivial. If you attempt to do any method overriding you will find
that things fail completely.

regs

Konrad

eadfrith

unread,
Dec 11, 2009, 4:51:37 PM12/11/09
to golang-nuts

On Dec 11, 11:40 am, Steven Blenkinsop <steven...@gmail.com> wrote:
> I wouldn't call this faking inheritance. Its one of the many
> constructs that the go system makes possible. I've seen this construct
> floating around on here a bit, and came up with it independantly at
> some point. Go lets you , by combining simple elements in simple ways,
> define complex relationships that other languages would either
> restrictively prescribe, or provide a dizzying multitude of special
> case syntaxes to achieve (ehem D). By combining elements in different
> ways you can create top down, bottom up, and looser relationships that
> don't require stuffing things into a hierarchy. I think that makes Go
> very powerful.

I completely agree. I'm having great fun exploring the different ways
you can combine type composition with interfaces to create interesting
structures.


eadfrith

unread,
Dec 11, 2009, 4:56:56 PM12/11/09
to golang-nuts


On Dec 11, 1:27 pm, konrad <kzielin...@gmail.com> wrote:
> The problem in the above is that when you call do2 the variable a
> points to an instance of IA not to an instance of A. You only get the
> component not the container. There is actually no way to get the
> container back. Go Composition does not fake inheritance.

I must be missing something. My understanding is that the variable a
holds an instance of type A, which is a struct. This struct has an
anoymous interface field, IA, to which it defers method calls. B is
able to insert itself into A, since it implements the IA interface,
and therefore gets the calls from A that would otherwise go to A
methods. B is therefore able to "inherit" the standard behaviour of A
while "overriding" the methods it chooses.

Steven Blenkinsop

unread,
Dec 11, 2009, 5:24:43 PM12/11/09
to golang-nuts
consider:

package main

type doer interface {
do();
}

type Doer struct {
doer;
}

func main()
{
d1 := new(Doer);
d1.doer = d1;
d1.do();
}

This code compiles and links fine. You'd want it to, if you'd actually
implemented a do() method. I wouldn't recommend using an anonymous
interface in anything beyond a simple couple, because doing so allows
your end state to implement an interface without ever defining the
method, and the problem could become hard to stamp out in more complex
structures. Naming the interface is a much safer approach (or naming
the type, depending on what you're exposing. Just avoid the looping in
any case that isn't very simple (a couple))

Naming the interface also makes it clear what you have to do to solve
konrad's issue with what you showed. All methods implemented on the
base type (and any type before the top level) should call the methods
of the (named) interface, if it wants those method calls to be
overrideable.

konrad

unread,
Dec 11, 2009, 10:16:35 PM12/11/09
to golang-nuts
The important information is in the 'Effective Go' document under
Embedding

> There's an important way in which embedding differs from subclassing. When we embed a type, the methods of that type become methods of the outer type, but > when they are invoked the receiver of the method is the inner type, not the outer one. In our example, when the Read method of a bufio.ReadWriter is invoked, it > has exactly the same effect as the forwarding method written out above; the receiver is the reader field of the ReadWriter, not the ReadWriter itself.

This is the curcial difference in an Object oriented system the
receiver of a method would be the outer type. Gerally you would only
see this clearly if you do try to override a method. Your overriding
implementation will be visible to methods on the outside but will not
be visible from methods in the contained type (which in an OO system
would be the super class).

Steven Blenkinsop

unread,
Dec 11, 2009, 11:56:43 PM12/11/09
to golang-nuts
On Dec 11, 10:16 pm, konrad <kzielin...@gmail.com> wrote:
> This is the curcial difference in an Object oriented system the
> receiver of a method would be the outer type. Gerally you would only
> see this clearly if you do try to override a method. Your overriding
> implementation will be visible to methods on the outside but will not
> be visible from methods in the contained type (which in an OO system
> would be the super class).

What you're missing is that you can embed an interface representing
the highest level struct (the "subtype" to apply the term loosely) and
call its methods. The only problem with this is that you need to know
beforehand what methods any intermediate struct is going to want to
call on the highest level struct, and all of your highest level
structs have to fully implement that interface. Really, you're not
building a class-style hierarchy. You're building a set of structs
that implement an interface with shared code.

And once you start thinking of it this way, you might start deciding
to use methods to wrap package functions, and define (sets of)
closures to embed into your types with accessor methods. Then you
realize that your inheritance hierarchy isn't really as essential as
you thought it was.

Santidhammo

unread,
Dec 12, 2009, 8:22:38 AM12/12/09
to golang-nuts
Thanks for making this statement. I think Go provides a very dynamic
way of sharing code between structures and implement faster versions
or encrypted versions ar different versions by "instructing" the outer
structure. ("instructing" is a play on the word "subclassing").

It certainly is different from mainline OO systems, but Go can still
make a variant amount of type hierarchies. The only thing that Go
requires is that you think about it. Which is a GOod thing.
Reply all
Reply to author
Forward
0 new messages