|
Archives
D Programming
D
D.gnu
digitalmars.D
digitalmars.D.bugs
digitalmars.D.dtl
digitalmars.D.dwt
digitalmars.D.announce
digitalmars.D.learn
digitalmars.D.debugger
C/C++ Programming
c++
c++.announce
c++.atl
c++.beta
c++.chat
c++.command-line
c++.dos
c++.dos.16-bits
c++.dos.32-bits
c++.idde
c++.mfc
c++.rtl
c++.stl
c++.stl.hp
c++.stl.port
c++.stl.sgi
c++.stlsoft
c++.windows
c++.windows.16-bits
c++.windows.32-bits
c++.wxwindows
digitalmars.empire
digitalmars.DMDScript
|
digitalmars.D.dtl - interfaces :-(
↑ ↓ ← → "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...
↑ ↓ ← → 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
↑ ↓ ← → 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
↑ ↓ ← → 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
↑ ↓ ← → 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
↑ ↓ ← → 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."
↑ ↓ ← → 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
↑ ↓ ← → 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
↑ ↓ ← → 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."
↑ ↓ ← → 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
↑ ↓ ← → 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
↑ ↓ ← → 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
↑ ↓ ← → 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
↑ ↓ ← → 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
↑ ↓ ← → =?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
↑ ↓ ← → 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
↑ ↓ ← → 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
↑ ↓ ← → =?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
↑ ↓ ← → 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
↑ ↓ ← → =?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
↑ ↓ ← → 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
↑ ↓ ← → 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
↑ ↓ ← → 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
↑ ↓ ← → 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
↑ ↓ ← → 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
↑ ↓ ← → 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
↑ ↓ ← → "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();
}
↑ ↓ ← → 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
↑ ↓ ← → "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.
↑ ↓ ← → 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
↑ ↓ ← → 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
↑ ↓ ← → =?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
↑ ↓ ← → "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.
↑ ↓ ← → 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
↑ ↓ ← → 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
↑ ↓ ← → 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
↑ ↓ ← → 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
↑ ↓ ← → 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
|
|