digitalmars.D.learn - opEquals does not work?
- Namespace (38/38) Jun 07 2013 Did I miss something?
- Namespace (2/2) Jun 07 2013 I got it. I must use Object instead of A... How ridiculous. I
- w0rp (10/12) Jun 07 2013 The class opEquals is quite like .equals in Java. You need to
- Namespace (3/15) Jun 07 2013 Yes, I remember. As I heard it the first time I thought it's
- w0rp (3/5) Jun 07 2013 opEquals for classes is interesting because you actually do need
- Jonathan M Davis (10/12) Jun 07 2013 I have an open pull request as part of the move to getting rid of opEqua...
- w0rp (2/7) Jun 07 2013 Oh, that's cool. I didn't know about that.
- bearophile (4/7) Jun 07 2013 http://d.puremagic.com/issues/show_bug.cgi?id=10292
- Namespace (2/9) Jun 07 2013 Thank you.
- =?UTF-8?B?QWxpIMOHZWhyZWxp?= (63/66) Jun 07 2013 I hope it supports delegate-taking toString overload for classes.[1]
- Jonathan M Davis (21/30) Jun 07 2013 It should be perfectly possible to declare such an overload now. It just...
Did I miss something? I expected this output ---- opEquals: 23 == 23 Equal 1 opEquals: 23 == 23 Equal 2 ---- by the following code, but I only get this: ---- opEquals: 23 == 23 Equal 2 ---- Code: [code] import std.stdio; class A { public: int id; this(int id) { this.id = id; } bool opEquals(const A a) const { writefln("opEquals: %d == %d", this.id, a.id); return a.id == this.id; } } void main() { A a1 = new A(23); A a2 = new A(23); if (a1 == a2) { writeln("Equal 1"); } if (a1.opEquals(a2)) { writeln("Equal 2"); } } [/code]
Jun 07 2013
I got it. I must use Object instead of A... How ridiculous. I thought this was already fixed...
Jun 07 2013
On Friday, 7 June 2013 at 20:51:13 UTC, Namespace wrote:I got it. I must use Object instead of A... How ridiculous. I thought this was already fixed...The class opEquals is quite like .equals in Java. You need to match the signature of Object, which is implicitly the base class of all classes. I think I recommend something like this. override bool opEquals(Object o) const { auto other = cast(A) o; // It's probably easy to miss out !is null here, which matters. return other !is null && this.id == other.id; }
Jun 07 2013
On Friday, 7 June 2013 at 20:58:40 UTC, w0rp wrote:On Friday, 7 June 2013 at 20:51:13 UTC, Namespace wrote:Yes, I remember. As I heard it the first time I thought it's because of the limited compiler and that it will fixed some day.I got it. I must use Object instead of A... How ridiculous. I thought this was already fixed...The class opEquals is quite like .equals in Java. You need to match the signature of Object, which is implicitly the base class of all classes. I think I recommend something like this. override bool opEquals(Object o) const { auto other = cast(A) o; // It's probably easy to miss out !is null here, which matters. return other !is null && this.id == other.id; }
Jun 07 2013
On Friday, 7 June 2013 at 21:02:15 UTC, Namespace wrote:Yes, I remember. As I heard it the first time I thought it's because of the limited compiler and that it will fixed some day.opEquals for classes is interesting because you actually do need to write 'Object' there because of type polymorphism.
Jun 07 2013
On Friday, June 07, 2013 22:51:12 Namespace wrote:I got it. I must use Object instead of A... How ridiculous. I thought this was already fixed...I have an open pull request as part of the move to getting rid of opEquals, opCmp, toHash, and toString from Object, and it would make it so that you could use something other than Object: https://github.com/D-Programming-Language/druntime/pull/459 However, due to D's overload rules, you will _always_ be forced to have an opEquals which takes the most base class that you can compare. But you should be able to do something like overload it with the derived class type and then alias the base classes' opEquals into the scope of the derived class. - Jonathan M Davis
Jun 07 2013
On Friday, 7 June 2013 at 21:18:12 UTC, Jonathan M Davis wrote:I have an open pull request as part of the move to getting rid of opEquals, opCmp, toHash, and toString from Object, and it would make it so that you could use something other than ObjectOh, that's cool. I didn't know about that.
Jun 07 2013
Jonathan M Davis:However, due to D's overload rules, you will _always_ be forced to have an opEquals which takes the most base class that you can compare.http://d.puremagic.com/issues/show_bug.cgi?id=10292 Bye, bearophile
Jun 07 2013
On Friday, 7 June 2013 at 21:42:36 UTC, bearophile wrote:Jonathan M Davis:Thank you.However, due to D's overload rules, you will _always_ be forced to have an opEquals which takes the most base class that you can compare.http://d.puremagic.com/issues/show_bug.cgi?id=10292 Bye, bearophile
Jun 07 2013
On 06/07/2013 02:18 PM, Jonathan M Davis wrote:I have an open pull request as part of the move to getting rid ofopEquals,opCmp, toHash, and toString from Object, and it would make it so that you could use something other than Object:I hope it supports delegate-taking toString overload for classes.[1] Ali [1] As a reminder to others who don't know or keep forgetting like me, :) toString has a more efficient toString overload. Unfortunately, it works only with structs at this point. I am way off-topic now but here is an example: import std.stdio; import std.format; struct Point { int x; int y; void toString(void delegate(const(char)[]) sink) const { formattedWrite(sink, "(%s,%s)", x, y); } } struct Color { ubyte r; ubyte g; ubyte b; void toString(void delegate(const(char)[]) sink) const { formattedWrite(sink, "RGB:%s,%s,%s", r, g, b); } } struct ColoredPoint { Color color; Point point; void toString(void delegate(const(char)[]) sink) const { formattedWrite(sink, "{%s;%s}", color, point); } } struct Poligon { ColoredPoint[] points; this(ColoredPoint[] points) { this.points = points; } void toString(void delegate(const(char)[]) sink) const { formattedWrite(sink, "%s", points); } } void main() { auto poligon = Poligon( [ ColoredPoint(Color(10, 10, 10), Point(1, 1)), ColoredPoint(Color(20, 20, 20), Point(2, 2)), ColoredPoint(Color(30, 30, 30), Point(3, 3)) ]); writeln(poligon); } The advantage of this method over the more-common toString() overload (the one that returns string) is that although there are still a total of 10 calls made to various toString() functions, those calls collectively produce a single string, not 10. Ali
Jun 07 2013
On Friday, June 07, 2013 14:53:44 Ali Çehreli wrote:On 06/07/2013 02:18 PM, Jonathan M Davis wrote:It should be perfectly possible to declare such an overload now. It just won't work when used through Object. If it doesn't work, then I expect that that's a bug in formattedWrite and friends. As far as overriding goes though, that'll depend on what the base classes of a class have declared. If they all declare toString without a delegate, then that's what you'd have to override to use toString using references of their type, whereas if they use the toString which takes a delegate, then that's what you'd have to override. But I don't see any reason that you can't have both just so long as the type of the reference that you're using has it. Howver, I supposed that a potential problem with formattedWrite and friends is that if you have two toString methods, it has to pick which one to use, and right now, it probably just picks the one from Object. Better behavior would be to us the delegate one if it's there and fall back to the non-delegate version if it's not. Long term though, formattedWrite et al will probably have the potential of not working at all with a class if we fully remove it from Object ike we intend to, since then there's no guarantee that a class or any of its base classes have even declared any toString. In any case, if toString with a delegate doesn't work with formattedWrite et al, then we need an enhancement request for that to be fixed. - Jonathan M DavisI have an open pull request as part of the move to getting rid ofopEquals,opCmp, toHash, and toString from Object, and it would make it so that youcould use something other than Object:I hope it supports delegate-taking toString overload for classes.[1]
Jun 07 2013