covariant return types

434 views
Skip to first unread message

serega

unread,
Dec 6, 2009, 6:53:44 PM12/6/09
to golang-nuts
Hi.
I see that to "satisfy" an interface a type must implement all methods
exactly as they are declared in the interface.
But if interface declares a method that returns another interface,
implementation must also use interface as a return type.
Consider the following example:
package main
import (
"fmt";
)

type A interface {
DoA();
}

type B interface {
GetA() A;
}

type AImpl struct {}

func (a AImpl) DoA() {
fmt.Println("DoA\n");
}

type BImpl struct {}

func (b BImpl) GetA() AImpl {
return AImpl{};
}

func main() {
var b B = BImpl{};
var a A = b.GetA();
a.DoA();
}

The compiler gives "BImpl is not B
missing GetA() (A)
do have GetA() (AImpl)"

The signature does not match exactly; however, AImpl is substitutable
for A.
Here is an example on covariant return types in Java
http://en.wikipedia.org/wiki/Covariant_return_type.

The example is fixable by changing GetA() to return A instead of
AImpl,
but that means BImpl depends on interface B.
Shouldn't compiler allows this substitution?

Sergey.

Peter Froehlich

unread,
Dec 6, 2009, 7:07:54 PM12/6/09
to serega, golang-nuts
I brought this up before as well and I very much like the idea of
covariant return types (and contravariant argument types) but since
the current (invariant) definition doesn't preclude that
generalization later I don't think it's necessary to fiddle with it
now while everybody is still trying to come to grips with the
language. Note, however, that the generalization (if it is ever made)
should apply to everything, not just methods, otherwise we'll add a
special case for one thing that doesn't fit well with the rest. I
guess the whole thing *may* run against the "no implicit conversions"
thing that Go has "going" too...
--
Peter H. Froehlich <http://www.cs.jhu.edu/~phf/>
Senior Lecturer | Director, Johns Hopkins Gaming Lab

Russ Cox

unread,
Dec 6, 2009, 8:01:36 PM12/6/09
to serega, golang-nuts
> Shouldn't compiler allows this substitution?

Even if the compiler allowed it, the program wouldn't run correctly.
http://research.swtch.com/2009/12/go-data-structures-interfaces.html
describes the data structures involved here.
The values returned by your two GetA methods have
different memory layouts. That can't work.
To make it work like in Java, Go would have
to adopt Java's object model (everything is a pointer,
dynamic method dispatch at the call sites, no itables),
which is a pretty fundamental change and unlikely
to happen.

Russ

Brian Slesinsky

unread,
Dec 6, 2009, 9:57:10 PM12/6/09
to golang-nuts

On Dec 6, 5:01 pm, Russ Cox <r...@golang.org> wrote:
> > Shouldn't compiler allows this substitution?
>
> Even if the compiler allowed it, the program wouldn't run correctly.http://research.swtch.com/2009/12/go-data-structures-interfaces.html
> describes the data structures involved here.
> The values returned by your two GetA methods have
> different memory layouts.  That can't work.
> To make it work like in Java, Go would have
> to adopt Java's object model (everything is a pointer,
> dynamic method dispatch at the call sites, no itables),
> which is a pretty fundamental change and unlikely
> to happen.

It wouldn't work in Java either, except that the compiler generates
hidden adapter methods in the subclass to do the type conversion. It
seems like a roughly analogous approach might work in Go: at the point
where one interface is being cast to another one, the compiler could
check whether there are some methods that have convertible return
types. If so it could generate a new interface value with conversion
functions substituted in the appropriate slots.

- Brian

Russ Cox

unread,
Dec 6, 2009, 10:00:24 PM12/6/09
to Brian Slesinsky, golang-nuts
> seems like a roughly analogous approach might work in Go: at the point
> where one interface is being cast to another one, the compiler could
> check whether there are some methods that have convertible return
> types. If so it could generate a new interface value with conversion
> functions substituted in the appropriate slots.

What if the conversion happens at run time in a dynamic check?

Russ

hong

unread,
Dec 7, 2009, 12:20:51 AM12/7/09
to golang-nuts
Go does not have native inheritance between types. The covariant
does not much much sense in general.

In your example, AImpl and A are different type. It requires explicit
cast to convert between them. If Go ever have generics, it will
solve some of your problems here.

Hong
> Here is an example on covariant return types in Javahttp://en.wikipedia.org/wiki/Covariant_return_type.
Reply all
Reply to author
Forward
0 new messages