www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.dtl - interfaces :-(

reply "Ben Hinkle" <ben.hinkle gmail.com> writes:
Well so far the interfaces in D are too clunky to be useful for MinTL 
(imho). They don't interact with objects very well so I'm going to test out 
using only abstract classes instead of interfaces. That way == will work and 
covariance becomes possible. So basically I imagine that the API would be 
the last thing I posted minus the interfaces. Anyway, the saga continues... 
May 24 2005
parent reply John Reimer <terminal.node gmail.com> writes:
Ben Hinkle wrote:
 Well so far the interfaces in D are too clunky to be useful for MinTL 
 (imho). They don't interact with objects very well so I'm going to test out 
 using only abstract classes instead of interfaces. That way == will work and 
 covariance becomes possible. So basically I imagine that the API would be 
 the last thing I posted minus the interfaces. Anyway, the saga continues... 
 
 

What's the status of D interfaces right now? Are there still troubles with them in any areas such as above? -JJR
Jan 13 2006
parent reply John Demme <me teqdruid.com> writes:
I've been watching the changelog and AFAIK nothing's changed, and I don't
think Walter's planning on changing anything.  The efficiency issues are
still there (according to Kris) and interfaces still aren't covariant with
ANYTHING making them utterly worthless.

I don't know if you've been watching my (slow) progress, but I've choosen to
nearly ignore interfaces altogether in mango.containers as Ben has for
MinTL.

Sure it'd be nice if Walter would fix some of these issues, but first he has
to be convinced that there are issues, something which I've had no success
in doing.

~John Demme

John Reimer wrote:

 Ben Hinkle wrote:
 Well so far the interfaces in D are too clunky to be useful for MinTL
 (imho). They don't interact with objects very well so I'm going to test
 out using only abstract classes instead of interfaces. That way == will
 work and covariance becomes possible. So basically I imagine that the API
 would be the last thing I posted minus the interfaces. Anyway, the saga
 continues...
 
 

What's the status of D interfaces right now? Are there still troubles with them in any areas such as above? -JJR

Jan 13 2006
next sibling parent reply John Reimer <terminal.node gmail.com> writes:
John Demme wrote:
 I've been watching the changelog and AFAIK nothing's changed, and I don't
 think Walter's planning on changing anything.  The efficiency issues are
 still there (according to Kris) and interfaces still aren't covariant with
 ANYTHING making them utterly worthless.

Okay... so that's the status. :( For my sake, could you explain what "covariant" means. I've seen this message before but don't fully comprehend its definition.
 I don't know if you've been watching my (slow) progress, but I've choosen to
 nearly ignore interfaces altogether in mango.containers as Ben has for
 MinTL.

I've taken a peek in mango.containers and, now that you mention it, recall that you were quite at odds with the interface implementation in D. But I hadn't really investigated much further. I'm trying to use interfaces in another project (converting C++ code). I'm not sure how far it will work. I've had to use an abstract class as a replacement in one context; but then a sub-class cannot "multiply inherit" from abstract classes as they can from interfaces, so to speak. So, if this is an issue, the design of the C++ project will need to be modified.
 Sure it'd be nice if Walter would fix some of these issues, but first he has
 to be convinced that there are issues, something which I've had no success
 in doing.

I agree that this is important. I hope we get noticed! Thanks, John. -JJR
Jan 13 2006
parent reply John Demme <me teqdruid.com> writes:
I'm not sure that I fully understand covariance either, but that's the word
that Walter used to say why the following doesn't work.

interface I
{
        I clone();
}

class A: I
{
        A clone();
}

Semantically, it works.  If you have a reference to an A:
A a = new A()
and want to make a clone that still uses an A reference:
A anotherA = a.clone()
It should work.  However, DMD does not support this (because I is not
covariant with A) and A's clone method has to return an I, so the previous
line of code has to be:
A anotherA = cast(A)a.clone();
Instead.  What's even worse is that interfaces aren't covariant with each
other, so the following doesn't work:
interface I
{
        I clone();
}

interface BabyI: I
{
}

class A: BabyI
{
        BabyI clone();
}

Since BabyI extends I, logically this should work.  But it doesn't for
implementation reasons which I don't understand (I think it's due to the
way DMD handles interfaces and vtables).  In short, because of this and the
poor interface codegen D's interfaces are pretty much shyte and mostly
worthless for mostly everything.  It's unfortunate, I like interfaces a
lot, but given these HUGE limitations, I can't use interfaces for anything
with any measure of complexity whatsoever.

I aplogize for any rants on this subject, I just find it VERY frusterating-
in the past I've considered going back to Java for most of my development
due to these issues, but then I started the JVM (and waited...) and decided
I'd just invent some ugly design hacks to get around D's impotence instead.

~John Demme


John Reimer wrote:

 John Demme wrote:
 I've been watching the changelog and AFAIK nothing's changed, and I don't
 think Walter's planning on changing anything.  The efficiency issues are
 still there (according to Kris) and interfaces still aren't covariant
 with ANYTHING making them utterly worthless.

Okay... so that's the status. :( For my sake, could you explain what "covariant" means. I've seen this message before but don't fully comprehend its definition.
 I don't know if you've been watching my (slow) progress, but I've choosen
 to nearly ignore interfaces altogether in mango.containers as Ben has for
 MinTL.

I've taken a peek in mango.containers and, now that you mention it, recall that you were quite at odds with the interface implementation in D. But I hadn't really investigated much further. I'm trying to use interfaces in another project (converting C++ code). I'm not sure how far it will work. I've had to use an abstract class as a replacement in one context; but then a sub-class cannot "multiply inherit" from abstract classes as they can from interfaces, so to speak. So, if this is an issue, the design of the C++ project will need to be modified.
 Sure it'd be nice if Walter would fix some of these issues, but first he
 has to be convinced that there are issues, something which I've had no
 success in doing.

I agree that this is important. I hope we get noticed! Thanks, John. -JJR

Jan 14 2006
next sibling parent reply Bruno Medeiros <daiphoenixNO SPAMlycos.com> writes:
John Demme wrote:
 I'm not sure that I fully understand covariance either, but that's the word
 that Walter used to say why the following doesn't work.
 
 interface I
 {
         I clone();
 }
 
 class A: I
 {
         A clone();
 }
 
 Semantically, it works.  If you have a reference to an A:
 A a = new A()
 and want to make a clone that still uses an A reference:
 A anotherA = a.clone()
 It should work.  However, DMD does not support this (because I is not
 covariant with A) and A's clone method has to return an I, so the previous
 line of code has to be:
 A anotherA = cast(A)a.clone();
 Instead.  What's even worse is that interfaces aren't covariant with each
 other, so the following doesn't work:
 interface I
 {
         I clone();
 }
 
 interface BabyI: I
 {
 }
 
 class A: BabyI
 {
         BabyI clone();
 }
 
 Since BabyI extends I, logically this should work.  But it doesn't for
 implementation reasons which I don't understand (I think it's due to the
 way DMD handles interfaces and vtables).  In short, because of this and the
 poor interface codegen D's interfaces are pretty much shyte and mostly
 worthless for mostly everything.  It's unfortunate, I like interfaces a
 lot, but given these HUGE limitations, I can't use interfaces for anything
 with any measure of complexity whatsoever.
 
 I aplogize for any rants on this subject, I just find it VERY frusterating-
 in the past I've considered going back to Java for most of my development
 due to these issues, but then I started the JVM (and waited...) and decided
 I'd just invent some ugly design hacks to get around D's impotence instead.
 
 ~John Demme
 
 
 John Reimer wrote:
 
 
John Demme wrote:

I've been watching the changelog and AFAIK nothing's changed, and I don't
think Walter's planning on changing anything.  The efficiency issues are
still there (according to Kris) and interfaces still aren't covariant
with ANYTHING making them utterly worthless.

Okay... so that's the status. :( For my sake, could you explain what "covariant" means. I've seen this message before but don't fully comprehend its definition.
I don't know if you've been watching my (slow) progress, but I've choosen
to nearly ignore interfaces altogether in mango.containers as Ben has for
MinTL.

I've taken a peek in mango.containers and, now that you mention it, recall that you were quite at odds with the interface implementation in D. But I hadn't really investigated much further. I'm trying to use interfaces in another project (converting C++ code). I'm not sure how far it will work. I've had to use an abstract class as a replacement in one context; but then a sub-class cannot "multiply inherit" from abstract classes as they can from interfaces, so to speak. So, if this is an issue, the design of the C++ project will need to be modified.
Sure it'd be nice if Walter would fix some of these issues, but first he
has to be convinced that there are issues, something which I've had no
success in doing.

I agree that this is important. I hope we get noticed! Thanks, John. -JJR


I didn't understand these posts, so I learned about Covariance and Contravariance (http://en.wikipedia.org/wiki/Parameter_covariance) , which I had only superficially heard about so far. This is another field where the terminology is *very* tricky, and subsequently, I now think that you are using an unclear, or even incorrect notion of covariance in your posts. (unless there some more idioms I'm not familiar with) In particular, I don't think the statement "because I is not covariant with A" is correct, since one does not speak of covariance as a relationship of an instance of something against an instance of something else (confusing, yes). Anyway, are you sure Walter said that? Covariance (and contravariance) is said of the inputs (parameters) or outputs (return types or exceptions) of something (methods in this case). I suspect that the issue you were speaking of was that D does not support covariant return types for methods of interfaces (as it does with classes). -- Bruno Medeiros - CS/E student "Certain aspects of D are a pathway to many abilities some consider to be... unnatural."
Jan 18 2006
parent reply John Reimer <terminal.node gmail.com> writes:
Bruno Medeiros wrote:

 I didn't understand these posts, so I learned about Covariance and 
 Contravariance (http://en.wikipedia.org/wiki/Parameter_covariance) , 
 which I had only superficially heard about so far.
 
 This is another field where the terminology is *very* tricky, and 
 subsequently, I now think that you are using an unclear, or even 
 incorrect notion of covariance in your posts. (unless there some more 
 idioms I'm not familiar with)
 In particular, I don't think the statement "because I is not covariant 
 with A" is correct, since one does not speak of covariance as a 
 relationship of an instance of something against an instance of 
 something else (confusing, yes). Anyway, are you sure Walter said that?
 Covariance (and contravariance) is said of the inputs (parameters) or 
 outputs (return types or exceptions) of something (methods in this 
 case). I suspect that the issue you were speaking of was that D does not 
 support covariant return types for methods of interfaces (as it does 
 with classes).
 
 

I don't believe John Demme was misusing the term "covariance." I believe he was just trying to restate what was given by the error message. That said, I do believe you are correct that the covariance issue relates to support for covariant return types for methods of interfaces. This is a good topic for further investigation. Thanks for the wiki link. -JJR
Jan 18 2006
parent reply John Demme <me teqdruid.com> writes:
John Reimer wrote:

 Bruno Medeiros wrote:
 
 I didn't understand these posts, so I learned about Covariance and
 Contravariance (http://en.wikipedia.org/wiki/Parameter_covariance) ,
 which I had only superficially heard about so far.
 
 This is another field where the terminology is *very* tricky, and
 subsequently, I now think that you are using an unclear, or even
 incorrect notion of covariance in your posts. (unless there some more
 idioms I'm not familiar with)
 In particular, I don't think the statement "because I is not covariant
 with A" is correct, since one does not speak of covariance as a
 relationship of an instance of something against an instance of
 something else (confusing, yes). Anyway, are you sure Walter said that?
 Covariance (and contravariance) is said of the inputs (parameters) or
 outputs (return types or exceptions) of something (methods in this
 case). I suspect that the issue you were speaking of was that D does not
 support covariant return types for methods of interfaces (as it does
 with classes).
 
 

I don't believe John Demme was misusing the term "covariance." I believe he was just trying to restate what was given by the error message. That said, I do believe you are correct that the covariance issue relates to support for covariant return types for methods of interfaces. This is a good topic for further investigation. Thanks for the wiki link. -JJR

Actually, the error message doesn't use the term. Yes, I probably was misusing it- as I previously said, I don't fully understand it. Either way, do you now understand the problem with DMD's interfaces, Bruno? ~John Demme
Jan 18 2006
parent reply Bruno Medeiros <daiphoenixNO SPAMlycos.com> writes:
John Demme wrote:
 John Reimer wrote:
 
 
Bruno Medeiros wrote:


I didn't understand these posts, so I learned about Covariance and
Contravariance (http://en.wikipedia.org/wiki/Parameter_covariance) ,
which I had only superficially heard about so far.

This is another field where the terminology is *very* tricky, and
subsequently, I now think that you are using an unclear, or even
incorrect notion of covariance in your posts. (unless there some more
idioms I'm not familiar with)
In particular, I don't think the statement "because I is not covariant
with A" is correct, since one does not speak of covariance as a
relationship of an instance of something against an instance of
something else (confusing, yes). Anyway, are you sure Walter said that?
Covariance (and contravariance) is said of the inputs (parameters) or
outputs (return types or exceptions) of something (methods in this
case). I suspect that the issue you were speaking of was that D does not
support covariant return types for methods of interfaces (as it does
with classes).

I don't believe John Demme was misusing the term "covariance." I believe he was just trying to restate what was given by the error message. That said, I do believe you are correct that the covariance issue relates to support for covariant return types for methods of interfaces. This is a good topic for further investigation. Thanks for the wiki link. -JJR

Actually, the error message doesn't use the term. Yes, I probably was misusing it- as I previously said, I don't fully understand it. Either way, do you now understand the problem with DMD's interfaces, Bruno? ~John Demme

Me? Well, implementation-wise, I have no ideia. Usage-wise, it is like I said: apparently D doesn't support covariant return types for methods of interfaces, yet it does for classes. That's why your abstract class examples work. Here's a simpler example: class Foo { Animal func(); } class FooBar: Foo { // override Animal func(); // would override (is invariant) override Monkey func(); // successfully overrides (is covariant) // override Object func(); // would not override (is contravariant) } When implementing interfaces methods, only invariants are allowed. I wonder what Walter's view on this is. Also, your comments that D's interfaces are highly useless because of this are quite exaggerated, or badly phrased. Java only had covariant return types (both for classes and interfaces) in the recent 1.5 version, but it's interfaces weren't useless before, obviously. -- Bruno Medeiros - CS/E student "Certain aspects of D are a pathway to many abilities some consider to be... unnatural."
Jan 19 2006
parent John Demme <me teqdruid.com> writes:
Bruno Medeiros wrote:

 John Demme wrote:
 John Reimer wrote:
 
 
Bruno Medeiros wrote:


I didn't understand these posts, so I learned about Covariance and
Contravariance (http://en.wikipedia.org/wiki/Parameter_covariance) ,
which I had only superficially heard about so far.

This is another field where the terminology is *very* tricky, and
subsequently, I now think that you are using an unclear, or even
incorrect notion of covariance in your posts. (unless there some more
idioms I'm not familiar with)
In particular, I don't think the statement "because I is not covariant
with A" is correct, since one does not speak of covariance as a
relationship of an instance of something against an instance of
something else (confusing, yes). Anyway, are you sure Walter said that?
Covariance (and contravariance) is said of the inputs (parameters) or
outputs (return types or exceptions) of something (methods in this
case). I suspect that the issue you were speaking of was that D does not
support covariant return types for methods of interfaces (as it does
with classes).

I don't believe John Demme was misusing the term "covariance." I believe he was just trying to restate what was given by the error message. That said, I do believe you are correct that the covariance issue relates to support for covariant return types for methods of interfaces. This is a good topic for further investigation. Thanks for the wiki link. -JJR

Actually, the error message doesn't use the term. Yes, I probably was misusing it- as I previously said, I don't fully understand it. Either way, do you now understand the problem with DMD's interfaces, Bruno? ~John Demme

Me? Well, implementation-wise, I have no ideia. Usage-wise, it is like I said: apparently D doesn't support covariant return types for methods of interfaces, yet it does for classes. That's why your abstract class examples work. Here's a simpler example: class Foo { Animal func(); } class FooBar: Foo { // override Animal func(); // would override (is invariant) override Monkey func(); // successfully overrides (is covariant) // override Object func(); // would not override (is contravariant) } When implementing interfaces methods, only invariants are allowed. I wonder what Walter's view on this is. Also, your comments that D's interfaces are highly useless because of this are quite exaggerated, or badly phrased. Java only had covariant return types (both for classes and interfaces) in the recent 1.5 version, but it's interfaces weren't useless before, obviously.

You don't know me personally, but I tend to exaggerate everything. Am I exaggerating here? Yeah, probably. I do use interfaces on occasion, but they've got so much potential to be so much more useful, and I want it! ~John Demme
Jan 19 2006
prev sibling next sibling parent reply John Reimer <terminal.node gmail.com> writes:
John Demme wrote:
 I'm not sure that I fully understand covariance either, but that's the word
 that Walter used to say why the following doesn't work.
 
 interface I
 {
         I clone();
 }
 
 class A: I
 {
         A clone();
 }
 
 Semantically, it works.  If you have a reference to an A:
 A a = new A()
 and want to make a clone that still uses an A reference:
 A anotherA = a.clone()

I don't get this. The two methods have different signatures, don't they? The interface: I clone(); is not the same as A clone() { return this; } // return "this" just to make it compile Thus, when you try to compile with dmd 0.143 you'll get function interface I.clone isn't implemented, a message that seems correct (or else there would be no way to differentiate a method that returned I or A) If you add an I clone() {} to class A, you get a compile error because there's a conflict between the two methods, which basically means that clone can't be overloaded this way due the potential ambiguities involved.
 It should work.  However, DMD does not support this (because I is not
 covariant with A) and A's clone method has to return an I, so the previous
 line of code has to be:
 A anotherA = cast(A)a.clone();
 Instead.  What's even worse is that interfaces aren't covariant with each
 other, so the following doesn't work:
 interface I
 {
         I clone();
 }
 
 interface BabyI: I
 {
 }
 
 class A: BabyI
 {
         BabyI clone();
 }
 
 Since BabyI extends I, logically this should work.  But it doesn't for
 implementation reasons which I don't understand (I think it's due to the
 way DMD handles interfaces and vtables).  In short, because of this and the
 poor interface codegen D's interfaces are pretty much shyte and mostly
 worthless for mostly everything.  It's unfortunate, I like interfaces a
 lot, but given these HUGE limitations, I can't use interfaces for anything
 with any measure of complexity whatsoever.
 

I'm not so sure these things are supposed to work quite like the above examples. It seems that there are more issues here than meet the eye. I think D's interface implementation might need some more thought, but it's no picnic no matter how one looks at the whole thing.
 I aplogize for any rants on this subject, I just find it VERY frusterating-
 in the past I've considered going back to Java for most of my development
 due to these issues, but then I started the JVM (and waited...) and decided
 I'd just invent some ugly design hacks to get around D's impotence instead.
 
 

Hey, no problem. I know how you feel. It would be nice to get a lot of things sorted out in D. :) -JJR
Jan 18 2006
parent reply John Demme <me teqdruid.com> writes:
See below.

John Reimer wrote:

 John Demme wrote:
 I'm not sure that I fully understand covariance either, but that's the
 word that Walter used to say why the following doesn't work.
 
 interface I
 {
         I clone();
 }
 
 class A: I
 {
         A clone();
 }
 
 Semantically, it works.  If you have a reference to an A:
 A a = new A()
 and want to make a clone that still uses an A reference:
 A anotherA = a.clone()

I don't get this. The two methods have different signatures, don't they? The interface: I clone(); is not the same as A clone() { return this; } // return "this" just to make it compile Thus, when you try to compile with dmd 0.143 you'll get function interface I.clone isn't implemented, a message that seems correct (or else there would be no way to differentiate a method that returned I or A) If you add an I clone() {} to class A, you get a compile error because there's a conflict between the two methods, which basically means that clone can't be overloaded this way due the potential ambiguities involved.

There are no potential ambiguities involved since A extends I. The problem with the current behavior is illustrated quite well by similar example as given above: interface IClonable { IClonable clone(); } class Foo: IClonable { IClonable clone(); } This compiles, however now if one has a reference to Foo and wants to clone it, they have to run the clone method and cast it to a Foo. However, if Foo.clone() was allowed to return a Foo reference, if one had a reference to a Foo and they clone it, they get a Foo. The interface also works as expected as if someone has an IClonable reference (which is actually a Foo) and they call the clone method they get a Foo referred to as an IClonable- which is perfectly valid considering that Foo extends IClonable. Also keep in mind that the following code DOES work: abstract class IClonable { IClonable clone(); } class Foo: IClonable { Foo clone(); } But what happens if Foo needs to inherient methods from a different class? Interfaces won't work properly to fill the gap here. Thus, they are worthless.
 
 
 It should work.  However, DMD does not support this (because I is not
 covariant with A) and A's clone method has to return an I, so the
 previous line of code has to be:
 A anotherA = cast(A)a.clone();
 Instead.  What's even worse is that interfaces aren't covariant with each
 other, so the following doesn't work:
 interface I
 {
         I clone();
 }
 
 interface BabyI: I
 {
 }
 
 class A: BabyI
 {
         BabyI clone();
 }
 
 Since BabyI extends I, logically this should work.  But it doesn't for
 implementation reasons which I don't understand (I think it's due to the
 way DMD handles interfaces and vtables).  In short, because of this and
 the poor interface codegen D's interfaces are pretty much shyte and
 mostly
 worthless for mostly everything.  It's unfortunate, I like interfaces a
 lot, but given these HUGE limitations, I can't use interfaces for
 anything with any measure of complexity whatsoever.
 

I'm not so sMYSQL_STRAIGHT_UPGRADE=1ure these things are supposed to work

 examples.  It seems that there are more issues here than meet the eye.
 I think D's interface implementation might need some more thought, but
 it's no picnic no matter how one looks at the whole thing.

The fact that something works as expected with an abstract class whereas it doesn't work with an interface is a good indication that there's just plain something wrong with DMD. Also note with the "BabyI" example, that if you change "interface" to "abstract class", it works properly. The way I see it is that interfaces should nearly be drop in replacements for abstract classes, but without method body inheritance, and allows multiple inheritance.
 
 
 I aplogize for any rants on this subject, I just find it VERY
 frusterating- in the past I've considered going back to Java for most of
 my development due to these issues, but then I started the JVM (and
 waited...) and decided I'd just invent some ugly design hacks to get
 around D's impotence instead.
 
 

Hey, no problem. I know how you feel. It would be nice to get a lot of things sorted out in D. :) -JJR

I've actually run in to this issue a whole lot. In the hopes that examples help clarify and convince (I find they help me a lot) here's some of the problems I had with this issue in DMD: In designing mango.containers, I wanted to make Container, List, MutableList and such all interfaces so that the implementations, such as ArrayList could extend anything they want. I thought it might, for instance, be able to create an MMArrayList which extends MemoryMappedFile (or something like this). However, a lot of the methods in these abstract classes return their type: abstract class Container { Container dup(); } But a Container itself isn't very useful, so whenever you call the dup() method you have to cast it to something useful- and having to cast like that is a HACK! I've had the same issue with neuralNexus (unreleased project). interface INode { INode getNameNode(); } class NNClientNode: XmlRpcObject, INode { INode getNameNode(); bit isConnected(); } Here if someone calls the getNameNode method on an NNClientNode, they can't use any special functionality of NNClientNode (like isConnected()) unless they cast back to it. It's a real PITA and it needs to get fixed. ~John Demme
Jan 18 2006
parent reply John Reimer <terminal.node gmail.com> writes:
John Demme wrote:
 See below.
 
 John Reimer wrote:
 
 John Demme wrote:
 I'm not sure that I fully understand covariance either, but that's the
 word that Walter used to say why the following doesn't work.

 interface I
 {
         I clone();
 }

 class A: I
 {
         A clone();
 }

 Semantically, it works.  If you have a reference to an A:
 A a = new A()
 and want to make a clone that still uses an A reference:
 A anotherA = a.clone()

I don't get this. The two methods have different signatures, don't they? The interface: I clone(); is not the same as A clone() { return this; } // return "this" just to make it compile Thus, when you try to compile with dmd 0.143 you'll get function interface I.clone isn't implemented, a message that seems correct (or else there would be no way to differentiate a method that returned I or A) If you add an I clone() {} to class A, you get a compile error because there's a conflict between the two methods, which basically means that clone can't be overloaded this way due the potential ambiguities involved.

There are no potential ambiguities involved since A extends I. The problem with the current behavior is illustrated quite well by similar example as given above: interface IClonable { IClonable clone(); } class Foo: IClonable { IClonable clone(); } This compiles, however now if one has a reference to Foo and wants to clone it, they have to run the clone method and cast it to a Foo. However, if Foo.clone() was allowed to return a Foo reference, if one had a reference to a Foo and they clone it, they get a Foo. The interface also works as expected as if someone has an IClonable reference (which is actually a Foo) and they call the clone method they get a Foo referred to as an IClonable- which is perfectly valid considering that Foo extends IClonable. Also keep in mind that the following code DOES work: abstract class IClonable { IClonable clone(); } class Foo: IClonable { Foo clone(); } But what happens if Foo needs to inherient methods from a different class? Interfaces won't work properly to fill the gap here. Thus, they are worthless.
 It should work.  However, DMD does not support this (because I is not
 covariant with A) and A's clone method has to return an I, so the
 previous line of code has to be:
 A anotherA = cast(A)a.clone();
 Instead.  What's even worse is that interfaces aren't covariant with each
 other, so the following doesn't work:
 interface I
 {
         I clone();
 }

 interface BabyI: I
 {
 }

 class A: BabyI
 {
         BabyI clone();
 }

 Since BabyI extends I, logically this should work.  But it doesn't for
 implementation reasons which I don't understand (I think it's due to the
 way DMD handles interfaces and vtables).  In short, because of this and
 the poor interface codegen D's interfaces are pretty much shyte and
 mostly
 worthless for mostly everything.  It's unfortunate, I like interfaces a
 lot, but given these HUGE limitations, I can't use interfaces for
 anything with any measure of complexity whatsoever.


 examples.  It seems that there are more issues here than meet the eye.
 I think D's interface implementation might need some more thought, but
 it's no picnic no matter how one looks at the whole thing.

The fact that something works as expected with an abstract class whereas it doesn't work with an interface is a good indication that there's just plain something wrong with DMD. Also note with the "BabyI" example, that if you change "interface" to "abstract class", it works properly. The way I see it is that interfaces should nearly be drop in replacements for abstract classes, but without method body inheritance, and allows multiple inheritance.
 I aplogize for any rants on this subject, I just find it VERY
 frusterating- in the past I've considered going back to Java for most of
 my development due to these issues, but then I started the JVM (and
 waited...) and decided I'd just invent some ugly design hacks to get
 around D's impotence instead.

things sorted out in D. :) -JJR

I've actually run in to this issue a whole lot. In the hopes that examples help clarify and convince (I find they help me a lot) here's some of the problems I had with this issue in DMD: In designing mango.containers, I wanted to make Container, List, MutableList and such all interfaces so that the implementations, such as ArrayList could extend anything they want. I thought it might, for instance, be able to create an MMArrayList which extends MemoryMappedFile (or something like this). However, a lot of the methods in these abstract classes return their type: abstract class Container { Container dup(); } But a Container itself isn't very useful, so whenever you call the dup() method you have to cast it to something useful- and having to cast like that is a HACK! I've had the same issue with neuralNexus (unreleased project). interface INode { INode getNameNode(); } class NNClientNode: XmlRpcObject, INode { INode getNameNode(); bit isConnected(); } Here if someone calls the getNameNode method on an NNClientNode, they can't use any special functionality of NNClientNode (like isConnected()) unless they cast back to it. It's a real PITA and it needs to get fixed. ~John Demme

I think I'm starting to see what you're getting at. Let me try to summarize what you are saying to see if I'm following this correctly: 1) We can use abstract classes to do what the interface should be able to do. But this is not good, because abstract classes don't function completely like interfaces. The fact that abstract classes can do what we expect interfaces to do reveals a defect in the current interface implementation. 2) In order to use the features of a class that extends an interface (as returned from a cloning function), we need to cast the returned interface reference to the class in question, which is awkward. example: NNClientNode node1 = cast(NNClientNode) specialNode.getNameNode(); Correct? -JJR
Jan 18 2006
parent reply John Demme <me teqdruid.com> writes:
John Reimer wrote:
[Edited out old stuff]
 
 I think I'm starting to see what you're getting at.
 
 Let me try to summarize what you are saying to see if I'm following this
 correctly:
 
 1) We can use abstract classes to do what the interface should be able
 to do.  But this is not good, because abstract classes don't function
 completely like interfaces.  The fact that abstract classes can do what
 we expect interfaces to do reveals a defect in the current interface
 implementation.
 
 
 2) In order to use the features of a class that extends an interface (as
 returned from a cloning function), we need to cast the returned
 interface reference to the class in question, which is awkward.
 
 example:
 
 NNClientNode node1 = cast(NNClientNode) specialNode.getNameNode();
 
 Correct?
 
 -JJR

The casting isn't just ackward, it's not safe through code changes, since it essentially eliminates compile-time type checking. And in addition to the fact the this stuff works with abstract classes and not with interfaces, it just plain makes sense (IMO). But you've essentially got it right... I may have had more examples and/arguments in the past, but I don't recall them at the moment. ~John Demme
Jan 18 2006
parent reply =?ISO-8859-1?Q?Jari-Matti_M=E4kel=E4?= <jmjmak utu.fi.invalid> writes:
John Demme wrote:
 John Reimer wrote:
 [Edited out old stuff]
 I think I'm starting to see what you're getting at.

 Let me try to summarize what you are saying to see if I'm following this
 correctly:

 1) We can use abstract classes to do what the interface should be able
 to do.  But this is not good, because abstract classes don't function
 completely like interfaces.  The fact that abstract classes can do what
 we expect interfaces to do reveals a defect in the current interface
 implementation.


 2) In order to use the features of a class that extends an interface (as
 returned from a cloning function), we need to cast the returned
 interface reference to the class in question, which is awkward.

 example:

 NNClientNode node1 = cast(NNClientNode) specialNode.getNameNode();

 Correct?

 -JJR

The casting isn't just ackward, it's not safe through code changes, since it essentially eliminates compile-time type checking. And in addition to the fact the this stuff works with abstract classes and not with interfaces, it just plain makes sense (IMO). But you've essentially got it right... I may have had more examples and/arguments in the past, but I don't recall them at the moment.

Why doesn't Walter want to fix this? I have already three stalled projects because of this. First I tried to use abstract classes, but D doesn't support multiple inheritance so now I cannot continue anymore. Isn't it a bit ironic that D ought to be practical language, but one must use C++/Java to circumvent these interface issues. -- Jari-Matti
Jan 19 2006
parent reply xs0 <xs0 xs0.com> writes:
 Why doesn't Walter want to fix this? I have already three stalled
 projects because of this. First I tried to use abstract classes, but D
 doesn't support multiple inheritance so now I cannot continue anymore.
 Isn't it a bit ironic that D ought to be practical language, but one
 must use C++/Java to circumvent these interface issues.

Well, AFAIK, the main problem here is that an object reference is not the same as an interface reference, even if they point to the same object (in other words, they point to different addresses). So, there is an important consequence that a method that returns an interface ref must return something else than a method that returns an object ref (even if the object otherwise implements the interface), meaning they're not covariant (or whatever it's called :) This is the same reason why casting from ISomething[] to Object[] doesn't work. I'm not sure what a good solution'd be, though.. If the two types of references are unified (made equal), simplifying a lot of things, all methods calls through interfaces will have to be resolved in runtime, and I'm not sure what the impact would be on speed etc., as it would require another level of indirection in method calls -- now its iref->vtable->method(), then it would be something like objref->getIface(...)->vtable->method(). It's the only thing I can think of, though, that would make interfaces work like in Java.. It wouldn't even be too hard to implement, I think, but getting Walter convinced is another issue :) xs0
Jan 19 2006
parent reply xs0 <xs0 xs0.com> writes:
 I'm not sure what a good solution'd be, though.. If the two types of 
 references are unified (made equal), simplifying a lot of things, all 
 methods calls through interfaces will have to be resolved in runtime, 
 and I'm not sure what the impact would be on speed etc., as it would 
 require another level of indirection in method calls -- now its 
 iref->vtable->method(), then it would be something like 
 objref->getIface(...)->vtable->method(). It's the only thing I can think 
 of, though, that would make interfaces work like in Java.. It wouldn't 
 even be too hard to implement, I think, but getting Walter convinced is 
 another issue :)

For what it's worth - I just tested it, and in Java calling the same "void method() {}" through an interface reference takes about 70% longer than through a class reference, and nobody seems to mind :) And an optimizing compiler would notice that the object in my test case was always the same, and could even do the method lookup only once, making them equally fast.. xs0
Jan 19 2006
parent reply =?ISO-8859-1?Q?Jari-Matti_M=E4kel=E4?= <jmjmak utu.fi.invalid> writes:
xs0 wrote:
 
 I'm not sure what a good solution'd be, though.. If the two types of
 references are unified (made equal), simplifying a lot of things, all
 methods calls through interfaces will have to be resolved in runtime,
 and I'm not sure what the impact would be on speed etc., as it would
 require another level of indirection in method calls -- now its
 iref->vtable->method(), then it would be something like
 objref->getIface(...)->vtable->method(). It's the only thing I can
 think of, though, that would make interfaces work like in Java.. It
 wouldn't even be too hard to implement, I think, but getting Walter
 convinced is another issue :)

For what it's worth - I just tested it, and in Java calling the same "void method() {}" through an interface reference takes about 70% longer than through a class reference, and nobody seems to mind :) And an optimizing compiler would notice that the object in my test case was always the same, and could even do the method lookup only once, making them equally fast..

Sounds very cool. Does this 70% mean that the time used between calling the method and executing the first line of the method is 70% longer? If it's so, this only hurts some recursive functions (assuming we have a stupid optimizer) since most of the time is spent _inside_ the methods, right? Besides, I like the Java interface implementation, it's very practical. -- Jari-Matti
Jan 19 2006
parent reply xs0 <xs0 xs0.com> writes:
Jari-Matti Mäkelä wrote:
 xs0 wrote:
 
I'm not sure what a good solution'd be, though.. If the two types of
references are unified (made equal), simplifying a lot of things, all
methods calls through interfaces will have to be resolved in runtime,
and I'm not sure what the impact would be on speed etc., as it would
require another level of indirection in method calls -- now its
iref->vtable->method(), then it would be something like
objref->getIface(...)->vtable->method(). It's the only thing I can
think of, though, that would make interfaces work like in Java.. It
wouldn't even be too hard to implement, I think, but getting Walter
convinced is another issue :)

For what it's worth - I just tested it, and in Java calling the same "void method() {}" through an interface reference takes about 70% longer than through a class reference, and nobody seems to mind :) And an optimizing compiler would notice that the object in my test case was always the same, and could even do the method lookup only once, making them equally fast..

Sounds very cool. Does this 70% mean that the time used between calling the method and executing the first line of the method is 70% longer?

Well, the method was empty, but I guess the way you put it would show about the same results.
 If
 it's so, this only hurts some recursive functions (assuming we have a
 stupid optimizer) since most of the time is spent _inside_ the methods,
 right? Besides, I like the Java interface implementation, it's very
 practical.

I agree it's very practical :) I'm not sure who else agrees, but many people (me included) would seem to think that the whole interface thing in D is currently not particularly useful, so it might be worth to rethink it a bit... xs0
Jan 19 2006
parent reply =?ISO-8859-1?Q?Jari-Matti_M=E4kel=E4?= <jmjmak utu.fi.invalid> writes:
xs0 wrote:
 Jari-Matti Mäkelä wrote:
 xs0 wrote:

 I'm not sure what a good solution'd be, though.. If the two types of
 references are unified (made equal), simplifying a lot of things, all
 methods calls through interfaces will have to be resolved in runtime,
 and I'm not sure what the impact would be on speed etc., as it would
 require another level of indirection in method calls -- now its
 iref->vtable->method(), then it would be something like
 objref->getIface(...)->vtable->method(). It's the only thing I can
 think of, though, that would make interfaces work like in Java.. It
 wouldn't even be too hard to implement, I think, but getting Walter
 convinced is another issue :)

For what it's worth - I just tested it, and in Java calling the same "void method() {}" through an interface reference takes about 70% longer than through a class reference, and nobody seems to mind :) And an optimizing compiler would notice that the object in my test case was always the same, and could even do the method lookup only once, making them equally fast..

Sounds very cool. Does this 70% mean that the time used between calling the method and executing the first line of the method is 70% longer?

Well, the method was empty, but I guess the way you put it would show about the same results.
 If
 it's so, this only hurts some recursive functions (assuming we have a
 stupid optimizer) since most of the time is spent _inside_ the methods,
 right? Besides, I like the Java interface implementation, it's very
 practical.

I agree it's very practical :) I'm not sure who else agrees, but many people (me included) would seem to think that the whole interface thing in D is currently not particularly useful, so it might be worth to rethink it a bit...

As far as I understand it, the current interfaces can only be used on simple single inheritance structures and on closed source products that want to hide the implementation from end users. At least I cannot come up with any creative ways in using them. I really hope Walter could think this over, maybe someone (like me) could help writing the docs or something. I fear after 1.0 release it would be too late to fix this anymore. -- Jari-Matti
Jan 19 2006
next sibling parent John Demme <me teqdruid.com> writes:
Jari-Matti Mäkelä wrote:
 As far as I understand it, the current interfaces can only be used on
 simple single inheritance structures and on closed source products that
 want to hide the implementation from end users. At least I cannot come
 up with any creative ways in using them.
 

Interface don't even work too well in single inheritance structures. They're really only OK if they don't extend anything and something that implements them doesn't add any functionality.
 I really hope Walter could think this over, maybe someone (like me)
 could help writing the docs or something. I fear after 1.0 release it
 would be too late to fix this anymore.
 

1.0 would be far too late to fix this. In my opinion, this issue has hampered D library development for some time and has already been ar large detriment to D. As for implementation, changing objects to always refer to the object (not an offset) to fix this problem (as xs0 suggests) is probably the best solution. "Make it right before you make it fast". Would it slow down interfaces? Yes, but if they're not very good, what's the point of using them anyway? I also suspect that there a a good deal of compiler optimizations that would significantly reduce the speed hit. I guess we'll see if Walter buys any of this (if he happens to be paying attention to this thread) ~John Demme
Jan 19 2006
prev sibling parent reply sean.fritz gmail.com writes:
In article <dqoho0$bmh$1 digitaldaemon.com>,
=?ISO-8859-1?Q?Jari-Matti_M=E4kel=E4?= says...
xs0 wrote:

As far as I understand it, the current interfaces can only be used on
simple single inheritance structures and on closed source products that
want to hide the implementation from end users. At least I cannot come
up with any creative ways in using them.

Well, FWIW I've been using invariant return type Java interfaces for years without realizing it was even a problem. I don't use abstract classes on a regular basis, because I tend to practice inversion of control and other design patterns that promote the use of interfaces as the only name coupling between classes wherever possible. I don't really, at this time understand the need for covariant return types. My first reaction to learning about them was to view them as needlessly complex, mostly useful in order to save one or two pointer lookups at method dispatch time in certain select situations. They are nice in that they do allow for compile time type checking, which leads into my second reaction. My second reaction was that all of these issues should be solvable by parameterizing(is that the correct D term for putting a type parameter on an interface?) the interface in a similar way to the way Comparable<T> is parameterized in Java. That is if D allows for overloading based on return types (which I do not know the answer to). While implementing parameter covariance through Comparable<T> has some serious issues, most notably you can never write the following code, it is one possible solution to this problem. //example illegal code -- you can't implement the same interface with //different type arguments in Java class A implements Comparable<A> { compareTo(A o) { .. } } class B extends A implements Comparable<B> { //compile time error B cannot //implement Comparable<A> and //Comparable<B> simultaneously .. } PS: Sorry if these points have already been made. I realize this is an old post. I just happened across this newsgroup and was reading from the beginning. Sean Fritz
Jun 15 2006
parent reply michal.minich gmail.com writes:
This is now possible in D, here's example, hope it's helpful


interface Comparable (T)
{
void compareTo(T o);
}

class A : Comparable!(A)
{
char[] textA;

void compareTo(A o)
{
printf ("A.compareTo: " ~ o.textA ~\n);
printf ( \n );
}	
}

class B : A, Comparable!(B)
{
char[] textB;

void compareTo(B o)
{
printf ("B.compareTo: " ~ o.textA ~\n);
printf ("B.compareTo: " ~ o.textB ~\n);
printf ( \n );
}
}


void main ()
{
A a = new A();
B b = new B();

a.textA = "TextA in instance of A";

b.textA = "TextA in instance of B";
b.textB = "TextB in instance of B";

a.compareTo(a);
a.compareTo(b);
b.compareTo(b);
}

/* the output is:
A.compareTo: TextA in instance of A

A.compareTo: TextA in instance of B

B.compareTo: TextA in instance of B
B.compareTo: TextB in instance of B
*/


In article <e6rg4h$1a9v$1 digitaldaemon.com>, sean.fritz gmail.com says...
In article <dqoho0$bmh$1 digitaldaemon.com>,
=?ISO-8859-1?Q?Jari-Matti_M=E4kel=E4?= says...
xs0 wrote:

As far as I understand it, the current interfaces can only be used on
simple single inheritance structures and on closed source products that
want to hide the implementation from end users. At least I cannot come
up with any creative ways in using them.

Well, FWIW I've been using invariant return type Java interfaces for years without realizing it was even a problem. I don't use abstract classes on a regular basis, because I tend to practice inversion of control and other design patterns that promote the use of interfaces as the only name coupling between classes wherever possible. I don't really, at this time understand the need for covariant return types. My first reaction to learning about them was to view them as needlessly complex, mostly useful in order to save one or two pointer lookups at method dispatch time in certain select situations. They are nice in that they do allow for compile time type checking, which leads into my second reaction. My second reaction was that all of these issues should be solvable by parameterizing(is that the correct D term for putting a type parameter on an interface?) the interface in a similar way to the way Comparable<T> is parameterized in Java. That is if D allows for overloading based on return types (which I do not know the answer to). While implementing parameter covariance through Comparable<T> has some serious issues, most notably you can never write the following code, it is one possible solution to this problem. //example illegal code -- you can't implement the same interface with //different type arguments in Java class A implements Comparable<A> { compareTo(A o) { .. } } class B extends A implements Comparable<B> { //compile time error B cannot //implement Comparable<A> and //Comparable<B> simultaneously .. } PS: Sorry if these points have already been made. I realize this is an old post. I just happened across this newsgroup and was reading from the beginning. Sean Fritz

Jun 20 2006
parent reply Sean Fritz <Sean_member pathlink.com> writes:
In article <e798bq$2gmi$1 digitaldaemon.com>, michal.minich gmail.com says...
This is now possible in D, here's example, hope it's helpful


interface Comparable (T)
{
void compareTo(T o);
}

class A : Comparable!(A)
{
char[] textA;

void compareTo(A o)
{
printf ("A.compareTo: " ~ o.textA ~\n);
printf ( \n );
}	
}

class B : A, Comparable!(B)
{
char[] textB;

void compareTo(B o)
{
printf ("B.compareTo: " ~ o.textA ~\n);
printf ("B.compareTo: " ~ o.textB ~\n);
printf ( \n );
}
}


void main ()
{
A a = new A();
B b = new B();

a.textA = "TextA in instance of A";

b.textA = "TextA in instance of B";
b.textB = "TextB in instance of B";

a.compareTo(a);
a.compareTo(b);
b.compareTo(b);
}

Does B also have a method/function (which do I use with D?) compareTo(A o)? Sean
Jun 20 2006
next sibling parent Kirk McDonald <kirklin.mcdonald gmail.com> writes:
Sean Fritz wrote:
 Does B also have a method/function (which do I use with D?) compareTo(A o)?
 

"A virtual member function is sometimes called a /method/." -Bjarne Stroustrup, The C++ Programming Language 3rd ed, section 12.2.6 In D, whether or not a member function is virtual is typically up to the compiler. In a sense, the distinction does not matter in D, unless you start declaring member functions as "final," which is basically saying "this is not virtual." This behavior is functionally similar to Java, in which all member functions are virtual; thus the term "method" is preferred in that language. "Member function" will always work, and "method" is usually fine in D. You'll usually catch me using "member function" by default, as I come from a C++ background. -Kirk McDonald
Jun 20 2006
prev sibling parent michal.minich gmail.com writes:
You have to write:
(cast(A)b).compareTo(a);

In case you use only b.compareTo(a); D issues an error, because the method
comparetTo in class B hides the implementation of this method in class a, so the
parameters of type B cannot be casted to A.

btw. (OT?) in C# is very nice possibility to imlement more interfaces in one
class with the same method signature. I don't know if this is possible in
Java...?

interface IA { void foo() }
interface IB { void foo() }
interface IC { void foo() }

class D : IA, IB, IC
{
void IA.foo () {} // explicitly implements foo() in interface IA
void foo () {} // implicitly implements foo() in interface IB
void IC.foo () {} // explicitly implements foo() in interface IC
}

void main ()
{
D d = new D();
d.foo() // calls foo implementing IB interface
((IA)d).foo () // calls foo implementing IA interface
((IB)d).foo () // calls foo implementing IA interface
}

I think the reason for this in C# is to solve problems where class have to
implement two absolutely different interface, but it happens that they have the
same method signature. It would be nice to have this possiblity in D.





In article <e79q4g$c4d$1 digitaldaemon.com>, Sean Fritz says...
In article <e798bq$2gmi$1 digitaldaemon.com>, michal.minich gmail.com says...
This is now possible in D, here's example, hope it's helpful


interface Comparable (T)
{
void compareTo(T o);
}

class A : Comparable!(A)
{
char[] textA;

void compareTo(A o)
{
printf ("A.compareTo: " ~ o.textA ~\n);
printf ( \n );
}	
}

class B : A, Comparable!(B)
{
char[] textB;

void compareTo(B o)
{
printf ("B.compareTo: " ~ o.textA ~\n);
printf ("B.compareTo: " ~ o.textB ~\n);
printf ( \n );
}
}


void main ()
{
A a = new A();
B b = new B();

a.textA = "TextA in instance of A";

b.textA = "TextA in instance of B";
b.textB = "TextB in instance of B";

a.compareTo(a);
a.compareTo(b);
b.compareTo(b);
}

Does B also have a method/function (which do I use with D?) compareTo(A o)? Sean

Jun 21 2006
prev sibling parent reply "Walter Bright" <newshound digitalmars.com> writes:
"John Demme" <me teqdruid.com> wrote in message 
news:dqae9p$2bhh$1 digitaldaemon.com...
 I'm not sure that I fully understand covariance either, but that's the 
 word
 that Walter used to say why the following doesn't work.

 interface I
 {
        I clone();
 }

 class A: I
 {
        A clone();
 }

It'll work if you rewrite it as: interface I { Object clone(); } class A: I { A clone(); }
Mar 09 2006
parent reply John Demme <me teqdruid.com> writes:
Walter Bright wrote:
 
 "John Demme" <me teqdruid.com> wrote in message
 news:dqae9p$2bhh$1 digitaldaemon.com...
 I'm not sure that I fully understand covariance either, but that's the
 word
 that Walter used to say why the following doesn't work.

 interface I
 {
        I clone();
 }

 class A: I
 {
        A clone();
 }

It'll work if you rewrite it as: interface I { Object clone(); } class A: I { A clone(); }

Fine. I'll give you a harder example: interface Map (K,V) { V get (K k); Map copy(); } class HashMap (K,V): Map!(K,V) { V get(K k) {} void rehash() {} HashMap copy() {} } ... And I've actually run into this problem. ~John Demme
Mar 09 2006
parent reply "Walter Bright" <newshound digitalmars.com> writes:
"John Demme" <me teqdruid.com> wrote in message 
news:dur87c$2m44$1 digitaldaemon.com...
 Fine.  I'll give you a harder example:

 interface Map (K,V)
 {
        V get (K k);
        Map copy();
 }

 class HashMap (K,V): Map!(K,V)
 {
        V get(K k) {}
        void rehash() {}
        HashMap copy() {}
 }

 ... And I've actually run into this problem.

Ok, but it will still work if Map.copy() is defined to return an Object rather than a Map. I concede it isn't as typesafe, in that whatever is derived from Object won't necessarilly be implementing Map, but it should work without ugly casting.
Mar 09 2006
parent reply John Demme <me teqdruid.com> writes:
Walter Bright wrote:
 "John Demme" <me teqdruid.com> wrote in message
 news:dur87c$2m44$1 digitaldaemon.com...
 Fine.  I'll give you a harder example:

 interface Map (K,V)
 {
        V get (K k);
        Map copy();
 }

 class HashMap (K,V): Map!(K,V)
 {
        V get(K k) {}
        void rehash() {}
        HashMap copy() {}
 }

 ... And I've actually run into this problem.

Ok, but it will still work if Map.copy() is defined to return an Object rather than a Map. I concede it isn't as typesafe, in that whatever is derived from Object won't necessarilly be implementing Map, but it should work without ugly casting.

C'mon... Can't we do better than this? And actually, it'll only work without ugly casting if you're working with a HashMap: Map!(char[], int) myMap = new HashMap!(char[],int)(); Map!(char[], int) originalMap = cast(Map!(char[],int)) myMap.clone(); The whole point of the interface, in this case, is to encourage people to disconnect their code from the implemantation of the map; encourage them to use the interface instead. ~John Demme
Mar 10 2006
parent reply Kris <Kris_member pathlink.com> writes:
In article <durcu5$2ulj$1 digitaldaemon.com>, John Demme says...
[snip]
C'mon... Can't we do better than this?  And actually, it'll only work
without ugly casting if you're working with a HashMap:

Map!(char[], int) myMap = new HashMap!(char[],int)();
Map!(char[], int) originalMap = cast(Map!(char[],int)) myMap.clone();

The whole point of the interface, in this case, is to encourage people to
disconnect their code from the implemantation of the map; encourage them to
use the interface instead.

Exactly. It's unfortunate that Interfaces are still something of a red-headed stepchild in D ~ It's not entirely clear that Walter uses Interfaces, or fully appreciates their powerful 'contractual' and decoupling aspects. There's no need for such tools when you're not working in a reasonably-sized team, or trying to build some kind of extensible library (or whatever). D interfaces have 'just enough' to make them useful in simple cases. For that, they are just fine ~ there's enough functionality there. Perhaps it'll mature? - Kris
Mar 10 2006
parent =?ISO-8859-1?Q?Jari-Matti_M=E4kel=E4?= <jmjmak utu.fi.invalid> writes:
Kris wrote:
 In article <durcu5$2ulj$1 digitaldaemon.com>, John Demme says...
 [snip]
 C'mon... Can't we do better than this?  And actually, it'll only work
 without ugly casting if you're working with a HashMap:

 Map!(char[], int) myMap = new HashMap!(char[],int)();
 Map!(char[], int) originalMap = cast(Map!(char[],int)) myMap.clone();

 The whole point of the interface, in this case, is to encourage people to
 disconnect their code from the implemantation of the map; encourage them to
 use the interface instead.

Exactly. It's unfortunate that Interfaces are still something of a red-headed stepchild in D ~ It's not entirely clear that Walter uses Interfaces, or fully appreciates their powerful 'contractual' and decoupling aspects. There's no need for such tools when you're not working in a reasonably-sized team, or trying to build some kind of extensible library (or whatever).

Very true. Semantically these uses guarantee the minimal functionality of a class instance. That's very valuable property in a proprietary software library, because the implementation is going to be hidden from the end user. It's a essential thing in other types of software too. Think of a RPG world full of players and monsters - it's full of subclasses and different interfaces. Creatures can cross-breed and do very complicated things to every possible object. What kind of object should a class method return then? This "advanced" use of interfaces prevents the coder from doing anything nasty in a class that knows nothing special about a passed object reference. The interfaces work as a greatest common denominator thus preventing the access to any properties that are "private" on a completely different abstraction level. Currently very simple operations require awfully lot of casting. It's definitely not practical to pass only Object references and then do a heavy amount of test&casting to find out the basic types of the objects. One other alternative would be to do a switch(class.getTypeInfo) { ... } to find out the correct casting, but it really makes the whole concept of interfaces rather pointless. We can already "emulate" some the functionality of these "advanced" interfaces by using abstract classes instead of interfaces, but the problem is that there's no way to emulate multiple inheritance with them.
 
 D interfaces have 'just enough' to make them useful in simple cases. For that,
 they are just fine ~ there's enough functionality there. Perhaps it'll mature?

I really hope so. If Walter doesn't provide any valid alternative or fix these, I must stop using D and switch to Java or Ruby. I know there are few people here who appreciate properly implemented interfaces, but I think a majority of us still don't get this. E.g. simply sorting an array of interface-type objects should be possible, but it isn't: Interface[] a; a ~= new instanceOfInterfaceAndAClass(); a ~= new instanceOfInterfaceAndASecondClass(); a.sort; // segfaults -- Jari-Matti
Mar 10 2006
prev sibling parent reply "Walter Bright" <newshound digitalmars.com> writes:
"John Demme" <me teqdruid.com> wrote in message 
news:dq9r0a$1u46$1 digitaldaemon.com...
 Sure it'd be nice if Walter would fix some of these issues, but first he 
 has
 to be convinced that there are issues, something which I've had no success
 in doing.

I think I've found a way to make the covariance thing work, so stay tuned.
Mar 11 2006
next sibling parent John Reimer <terminal.node gmail.com> writes:
Walter Bright wrote:
 "John Demme" <me teqdruid.com> wrote in message 
 news:dq9r0a$1u46$1 digitaldaemon.com...
 Sure it'd be nice if Walter would fix some of these issues, but first he 
 has
 to be convinced that there are issues, something which I've had no success
 in doing.

I think I've found a way to make the covariance thing work, so stay tuned.

!!!!! WOW! Okay, I got to calm down now.... :D -JJR
Mar 11 2006
prev sibling parent reply John Demme <me teqdruid.com> writes:
Walter Bright wrote:

 
 "John Demme" <me teqdruid.com> wrote in message
 news:dq9r0a$1u46$1 digitaldaemon.com...
 Sure it'd be nice if Walter would fix some of these issues, but first he
 has
 to be convinced that there are issues, something which I've had no
 success in doing.

I think I've found a way to make the covariance thing work, so stay tuned.

Great; thanks. Just out of curiosity, what made you take this issue up now instead of earlier (or later)? ~John Demme
Mar 12 2006
parent reply John Reimer <terminal.node gmail.com> writes:
John Demme wrote:
 Walter Bright wrote:
 
 "John Demme" <me teqdruid.com> wrote in message
 news:dq9r0a$1u46$1 digitaldaemon.com...
 Sure it'd be nice if Walter would fix some of these issues, but first he
 has
 to be convinced that there are issues, something which I've had no
 success in doing.


Great; thanks. Just out of curiosity, what made you take this issue up now instead of earlier (or later)? ~John Demme

Uh... it's okay Walter, um... don't listen to him... he didn't mean it, honest! <* grabs John Demme, stuffs a sock in his mouth, and drags him away... before Walter changes his mind *> ;) -JJR
Mar 12 2006
parent reply John Demme <me teqdruid.com> writes:
John Reimer wrote:

 John Demme wrote:
 Walter Bright wrote:
 
 "John Demme" <me teqdruid.com> wrote in message
 news:dq9r0a$1u46$1 digitaldaemon.com...
 Sure it'd be nice if Walter would fix some of these issues, but first
 he has
 to be convinced that there are issues, something which I've had no
 success in doing.

tuned.

Great; thanks. Just out of curiosity, what made you take this issue up now instead of earlier (or later)? ~John Demme

Uh... it's okay Walter, um... don't listen to him... he didn't mean it, honest! <* grabs John Demme, stuffs a sock in his mouth, and drags him away... before Walter changes his mind *> ;) -JJR

I'm sorry... I didn't mean anything by it... Should I reword to: Great! Thanks! I thought that the exclamation marks might seem sarcastic. And I really was just curious what prompted Walter to bring up the issue now, considering that I haven't mentioned in awhile.... Didn't mean anything by my post-- certainly not anything negative. ~John Demme
Mar 12 2006
parent John Reimer <terminal.node gmail.com> writes:
John Demme wrote:
 John Reimer wrote:
 
 John Demme wrote:
 Walter Bright wrote:

 "John Demme" <me teqdruid.com> wrote in message
 news:dq9r0a$1u46$1 digitaldaemon.com...
 Sure it'd be nice if Walter would fix some of these issues, but first
 he has
 to be convinced that there are issues, something which I've had no
 success in doing.

tuned.

Just out of curiosity, what made you take this issue up now instead of earlier (or later)? ~John Demme

Uh... it's okay Walter, um... don't listen to him... he didn't mean it, honest! <* grabs John Demme, stuffs a sock in his mouth, and drags him away... before Walter changes his mind *> ;) -JJR

I'm sorry... I didn't mean anything by it... Should I reword to: Great! Thanks! I thought that the exclamation marks might seem sarcastic. And I really was just curious what prompted Walter to bring up the issue now, considering that I haven't mentioned in awhile.... Didn't mean anything by my post-- certainly not anything negative. ~John Demme

I, in turn, apologize for being rediculous. It was all in good fun, John. You had a valid question. I just couldn't help playing on it a bit. I think I over did it! I'm curious too what prompted Walter's response, but I imagine it just had to do with him finally catching up to this post after all this time. :P Sorry, man. I must have been just a little too giddy. -JJR
Mar 12 2006