Hi!
IMHO defining the value used for the array key should be provided by the
user, like Lester Caine said. Using a state or location based hash behaves
very unexpectedly and I doubt it would be used very much because of that.
Regarding __toString vs. __hash. It depends on what __toString really is
for. Now that there is a dedicated __debugInfo method, should __toString
enable an object to be used as a string without exception? In this case
there is no need for a separate method. Having a separate method might
actually be confusing. "When a string is expected __toString is called,
except when ..."
If that is not the purpose of __toString() than a separate method makes
more sense. I agree with johannes that __toString is often used for
debugging. I do that quite a bit. However since this would be new
functionality there is no BC break and users can be informed before using
it.
I tried to summarize the four approaches, just to make sure I understood
them correctly.
Using __toString()
toString not set will lead all instances to use the same (empty) array key
thus overwriting each other.
toString is often used to generate a string represantation of the class.
Imagine an emailClass, where toString return the email body. This would
lead to huge unwieldy array keys, though technically fine.
toString then has three jobs:
1. Output for debug (even though there is a new function for that, it
is still often used for that)
2. Textual representation, like an email-body or the content of a
stream.
3. array key
Currently the following error is thrown, when no __toString function is
defined
"Fatal error: Object of class O could not be converted to string". If it
read
"Fatal error: Object of class O could not be converted to string. Expected
method __toString()." It would point users in the right direction.
new magic method __hash
This relieves the ambiguity of __toString. It also enables the user to
define a key that is sensible for his use case, for example a user id or
database id.
Currently it issues a warning "Warning: Illegal offset type". If a new
magicc method is implemented than it should read "Warning: Illegal offset
type object. Object has no method __hash()"
state based Hash
A state based hash can be made somewhat readable, but changing state
changes the hash.
$a = new MyClass();
$a->foo = 'bar';
$d = array( $a => 'It Works');
$a->foo = 'buzz';
echo $d[$a]; // Notice: Undefined index
On the other hand this would work (Imagine storing something in the session
or database and trying to access it from a different instance or from a
later request)
$a = new MyClass();
$a->foo = 'bar';
$d = array( $a => 'It Works');
$b = serialize($a);
$a = unserialie($b);
echo $d[$a]; // It Works!
internal pointer based Hash
Changing the state of the object would not change its hash so this works:
$a = new MyClass();
$a->foo = 'bar';
$d = array( $a => 'It Works');
$a->foo = 'buzz';
echo $d[$a]; // It works
But this would not work
$a = new MyClass();
$a->foo = 'bar';
$d = array( $a => 'It Works);
$b = serialize($a);
$a = unserialie($b);
echo $d[$a]; // Notice: Undefined index
-- john