Take a look at this simple class I'm building as the base to store the results of string matching algorithms:
/** Match of a single pattern in full to a single text. */
class Match {
uint Tpos;
this(in uint Tpos) { this.Tpos = Tpos; }
override string toString() {
return text("Match: Text@",Tpos);
}
}
Here's where things get weird:
auto m1 = new Match(1), m2 = new Match(1);
writeln(m1.toHash());
writeln(m2.toHash());
writeln(m1 == m2);
prints
4464528
4464512
false
I see no reason why these two objects should not be considered equal by default. I suppose I could write a custom toHash()
and opEquals()
function, but that seems like overkill. According to Andrei Alexandrescu's book on the D programming language (great book!), "By default, the hash is computed by using the bitwise representation of the object." Any ideas out there?
Objects are not compared by value: two objects are not equal even if they have the same properties and values. This is true of arrays too: even if they have the same values in the same order. Objects are sometimes called reference types to distinguish them from JavaScript's primitive types.
The equals() method of the Object class compare the equality of two objects. The two objects will be equal if they share the same memory address. Syntax: public boolean equals(Object obj)
We can use == operators for reference comparison (address comparison) and . equals() method for content comparison. In simple words, == checks if both objects point to the same memory location whereas . equals() evaluates to the comparison of values in the objects.
To determine if two objects are not identical Set up a Boolean expression to test the two objects. In your testing expression, use the IsNot operator with the two objects as operands. IsNot returns True if the objects do not point to the same class instance.
From the source code (dmd2/src/druntime/src/object_.d):
class Object
{
/* snip */
/**
* Compute hash function for Object.
*/
hash_t toHash() @trusted nothrow
{
// BUG: this prevents a compacting GC from working, needs to be fixed
return cast(hash_t)cast(void*)this;
}
/* snip */
/**
* Returns !=0 if this object does have the same contents as obj.
*/
equals_t opEquals(Object o)
{
return this is o;
}
}
So the answer is simply that's the way the code is written - they do an identity check rather than a content check. Why is it this way? I don't really know, but my guess is it was simple to write originally and works well enough that nobody has bothered to come back to it and change it.
On the newsgroup, there's been some discussion of removing these functions from Object entirely, so if you want == on your classes, you'll have to implement something. But the time it takes for newsgroup talk to become action when it comes to things like this is usually pretty long. And they might change their minds.
The best way of using class equality currently and probably in the foreseeable future is to write your own opEquals method in the class.
You have to implement toHash
on your own, since Object.toHash
depends on the address. If I remember correctly it's just a return cast(hash_t)cast(void*)this
.
EDIT: Yes, I remember correctly: https://github.com/D-Programming-Language/druntime/blob/master/src/object_.d#L88
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With