$h = Hash::AsObject->new; $h->foo(123); print $h->foo; # prints 123 print $h->{'foo'}; # prints 123 $h->{'bar'}{'baz'} = 456; print $h->bar->baz; # prints 456
It's designed to act as much like a plain hash as possible; this means, for example, that you can use methods like "DESTROY" to get or set hash elements with that name. See below for more information.
In order to behave properly in all cases, however, a number of special methods and functions must be supported. Some of these are defined while others are simply emulated in AUTOLOAD.
$h = Hash::AsObject->new; $h = Hash::AsObject->new(\%some_hash); $h = Hash::AsObject->new(%some_other_hash);
Create a new Hash::AsObject.
If called as an instance method, this accesses a hash element 'new':
$h->{'new'} = 123; $h->new; # 123 $h->new(456); # 456
$h->{'AUTOLOAD'} = 'abc'; $h->AUTOLOAD; # 'abc' $h->AUTOLOAD('xyz') # 'xyz'
Hash::AsObject::AUTOLOAD recognizes when AUTOLOAD is begin called as an instance method, and treats this as an attempt to get or set the 'AUTOLOAD' hash element.
$h->{'DESTROY'} = []; $h->DESTROY; # [] $h->DESTROY({}) # {}
"DESTROY" is called automatically by the Perl runtime when an object goes out of scope. A Hash::AsObject can't distinguish this from a call to access the element $h->{'DESTROY'}, and so it blithely gets (or sets) the hash's 'DESTROY' element; this isn't a problem, since the Perl interpreter discards any value that DESTROY returns when called automatically.
When called as a class method, nothing happens.
The methods "can()" and "isa()" are special, because they're defined in the "UNIVERSAL" class that all packages automatically inherit from. Unfortunately, this means that you can't use Hash::AsObject to access elements 'can' and 'isa'.
Storing a hash directly into an element of a Hash::AsObject instance has the effect of blessing that hash into Hash::AsObject.
For example, the following code:
my $h = Hash::AsObject->new; my $foo = { 'bar' => 1, 'baz' => 2 }; print ref($foo), "\n"; $h->foo($foo); print ref($foo), "\n";
Produces the following output:
HASH Hash::AsObject
I could fix this, but then code like the following would throw an exception, because "$h->foo($foo)" will return a plain hash reference, not an object:
$h->foo($foo)->bar;
Well, I can make "$h->foo($foo)->bar" work, but then code like this won't have the desired effect:
my $foo = { 'bar' => 123 }; $h->foo($foo); $h->foo->bar(456); print $foo->{'bar'}; # prints 123 print $h->foo->bar; # prints 456
I suppose I could fix that, but that's an awful lot of work for little apparent benefit.
Let me know if you have any thoughts on this.
The blessing of hashes stored in a Hash::AsObject might be considered a bug. Or a feature; it depends on your point of view.
use Hash::AsObject 'deleter' => 'kill'; $h = Hash::AsObject->new({'one' => 1, 'two' => 2}); kill $h, 'one';
That might seem to violate the prohibition against exporting functions from object-oriented packages, but then technically it wouldn't be exporting it from anywhere since the function would be constructed by hand. Alternatively, it could work like this:
use Hash::AsObject 'deleter' => 'kill'; $h = Hash::AsObject->new({'one' => 1, 'two' => 2}); $h->kill('one');
But, again, what if the hash contained an element named 'kill'?
[% foo.bar.baz(qux) %]
Made me yearn to write Perl code like this:
foo->bar->baz($qux);
This program is free software; you can redistribute it and modify it under the same terms as Perl itself.