Jump to page: 1 2 3
Thread overview
Restriction on interface function types
Mar 12, 2014
Steve Teale
Mar 12, 2014
monarch_dodra
Mar 12, 2014
Steve Teale
Mar 12, 2014
Adam D. Ruppe
Mar 12, 2014
Steve Teale
Mar 12, 2014
Steve Teale
Mar 12, 2014
Steve Teale
Mar 12, 2014
Steve Teale
Mar 12, 2014
Iain Buclaw
Mar 13, 2014
Steve Teale
Mar 12, 2014
monarch_dodra
Mar 12, 2014
monarch_dodra
Mar 12, 2014
Steve Teale
Mar 12, 2014
Chris Williams
Mar 12, 2014
Frustrated
March 12, 2014
interface I
{
   auto myType();
}

class A: I
{
   auto myType() { return cast(A) null; }
}

void main()
{
   I x = getSomeI();
   typeof(x.myType()) y;
}
March 12, 2014
On Wednesday, 12 March 2014 at 10:57:10 UTC, Steve Teale wrote:
> interface I
> {
>    auto myType();
> }
>
> class A: I
> {
>    auto myType() { return cast(A) null; }
> }
>
> void main()
> {
>    I x = getSomeI();
>    typeof(x.myType()) y;
> }

Seems like you want covariance? I don't see how else having an interface that returns "auto" could work.

That said, I'd expect this to work:

//----
interface I
{
   I myType();
}

class A: I
{
   //auto myType() { return cast(A) null; } //Nope
   A myType() { return cast(A) null; } //OK
}
//----

But app
March 12, 2014
On Wed, 12 Mar 2014 06:57:08 -0400, Steve Teale <steve.teale@britseyeview.com> wrote:

> interface I
> {
>     auto myType();
> }
>
> class A: I
> {
>     auto myType() { return cast(A) null; }
> }
>
> void main()
> {
>     I x = getSomeI();
>     typeof(x.myType()) y;
> }

What you want simply isn't possible. An interface binds at runtime, and you need to declare types at compile-time. You can't use an interface method to define the type of y.

-Steve
March 12, 2014
On Wednesday, 12 March 2014 at 11:13:00 UTC, monarch_dodra wrote:
>
> That said, I'd expect this to work:
>
> //----
> interface I
> {
>    I myType();
> }
>
> class A: I
> {
>    //auto myType() { return cast(A) null; } //Nope
>    A myType() { return cast(A) null; } //OK
> }
> //----
>
> Yup, covariance desired, but

import std.stdio;

interface I
{
   I myType();
}

class A: I
{
   A myType() { return cast(A) null; }
   void foo() { writeln("foo"); }
}

void main()
{
   I a = new A();
   writeln(typeof(a.myType()).stringof);
}

returns I

Seems like a bug to me.

Steve

March 12, 2014
On Wednesday, 12 March 2014 at 13:05:07 UTC, Steve Teale wrote:
>    I a = new A();
>
> Seems like a bug to me.


You are working through the interface, so the type will be what was written in the interface. If you made that "A a = new A();", then you could see type A on the override.

But the interface has no way of knowing which child class is there at compile time so it has to work through base types only.
March 12, 2014
On Wed, 12 Mar 2014 09:05:05 -0400, Steve Teale <steve.teale@britseyeview.com> wrote:

> On Wednesday, 12 March 2014 at 11:13:00 UTC, monarch_dodra wrote:
>>
>> That said, I'd expect this to work:
>>
>> //----
>> interface I
>> {
>>    I myType();
>> }
>>
>> class A: I
>> {
>>    //auto myType() { return cast(A) null; } //Nope
>>    A myType() { return cast(A) null; } //OK
>> }
>> //----
>>
>> Yup, covariance desired, but
>
> import std.stdio;
>
> interface I
> {
>     I myType();
> }
>
> class A: I
> {
>     A myType() { return cast(A) null; }
>     void foo() { writeln("foo"); }
> }
>
> void main()
> {
>     I a = new A();
>     writeln(typeof(a.myType()).stringof);
> }
>
> returns I
>
> Seems like a bug to me.

No, not a bug. What you want is actually not possible.

To demonstrate further:

void bad(I i)
{
   typeof(i.myType()) x;
}

class A : I
{
   A myType() { return cast(A)null;}
}

class B : I
{
   B myType() {return cast(B) null;}
}

void main()
{
   I[] arr = [new A, new B];
   foreach(i; arr) {bad(i);}
}

How is the compiler to build it's one copy of bad? Should x be typed as A or B? Or something not even seen in this module that could derive from I?

-Steve
March 12, 2014
On Wednesday, 12 March 2014 at 11:56:43 UTC, Steven Schveighoffer wrote:
> On Wed, 12 Mar 2014 06:57:08 -0400, Steve Teale <steve.teale@britseyeview.com> wrote:
>
>
> What you want simply isn't possible. An interface binds at runtime, and you need to declare types at compile-time. You can't use an interface method to define the type of y.
>
> -Steve

Steve

OK, it was a bad illustrative example, but

(cast(typeof(a.myType()) whatever).foo();

could be useful, when foo() is not in the interface.

It was the failure of auto in an interface that I was remarking on - should at least be documented. Also the covariant return values as suggested by md don't work either.

Steve
March 12, 2014
On Wed, 12 Mar 2014 09:13:08 -0400, Steve Teale <steve.teale@britseyeview.com> wrote:

> On Wednesday, 12 March 2014 at 11:56:43 UTC, Steven Schveighoffer wrote:
>> On Wed, 12 Mar 2014 06:57:08 -0400, Steve Teale <steve.teale@britseyeview.com> wrote:
>>
>>
>> What you want simply isn't possible. An interface binds at runtime, and you need to declare types at compile-time. You can't use an interface method to define the type of y.
>>
>> -Steve
>
> Steve
>
> OK, it was a bad illustrative example, but
>
> (cast(typeof(a.myType()) whatever).foo();
>
> could be useful, when foo() is not in the interface.
>
> It was the failure of auto in an interface that I was remarking on - should at least be documented. Also the covariant return values as suggested by md don't work either.

Auto doesn't work if you don't define what it returns. Auto is not a type in itself, it means "infer the type". If there's nothing to infer with, it's an error.

-Steve
March 12, 2014
On Wednesday, 12 March 2014 at 13:12:20 UTC, Steven Schveighoffer wrote:
> On Wed, 12 Mar 2014 09:05:05 -0400, Steve Teale <steve.teale@britseyeview.com> wrote:

> How is the compiler to build it's one copy of bad? Should x be typed as A or B? Or something not even seen in this module that could derive from I?
>
> -Steve

Let's take bad() away, and instead:

class A : I
{
   A myType() { return cast(A)null;}
   final void foo();
}

class B : I
{
   B myType() {return cast(B) null;}
   final void bar();
}

void main()
{
   I[] arr = [new A, new B];
   foreach(i; arr) { (cast(typeof(i.myType()) i).foo() }
}

myType() is a virtual function, so calling it through the interface type should get the correct version right?, and then the cast should cause a call to A or B.
March 12, 2014
On Wednesday, 12 March 2014 at 13:34:33 UTC, Steve Teale wrote:
> class A : I
> {
>    A myType() { return cast(A)null;}
>    final void foo();
> }
>
> class B : I
> {
>    B myType() {return cast(B) null;}
>    final void bar();
> }
>
> void main()
> {
>    I[] arr = [new A, new B];
>    foreach(i; arr) { (cast(typeof(i.myType()) i).foo() }
> }
>
> myType() is a virtual function, so calling it through the interface type should get the correct version right?, and then the cast should cause a call to A or B.

Aargh - not final void foo() and final void bar(), just void foo() in each case - a virtual function not mentioned by the interface.
« First   ‹ Prev
1 2 3