How can I stop or allow a perl object to be used as a hashref?

103 Views Asked by At

I have a Perl class which is a based on a blessed hashref ( https://github.com/kylemhall/Koha/blob/master/Koha/Object.pm )

This is a community based project, with many developers of varying skill.

What I've seen is some developers accidentally using our objects as hashrefs. The actual data is not stored in the blessed hashref, but in a dbic object that is stored in the hashref ( in $self->{_result} ). When the dev tries something like $object->{id} perl doesn't complain, it just returns undef, as would be expected.

What I'd like to do is to either A) Make the script explode with an error when this happens B) Allow the use of the hashref syntax for setting / getting values in the dbic objects stored in $self->{_result}

I tried using:

use overload '%{}' => \&get_hashref;

but when I do this, get_hashref is called any time a regular method is called! This makes sense in a way, since the object itself is a hashref. I'm sure this has something to do with the Perl internals for blessed hashrefs as objects.

Is what I'm trying to accomplish even possible?

2

There are 2 best solutions below

3
On BEST ANSWER

I suggest using a scalar-based or array-based object instead of a hash-based object. This is a cheap (efficient) solution since it simply causes the offender to run afoul of existing type checks.

For example, the object produced by the following is simply a reference to the actual object. Just use $$self instead of $self in the methods.

$ perl -e'
   sub new {
      my $class = shift;
      my $self = bless(\{}, $class);
      # $$self->{...} = ...;
      return $self;
   }
   my $o = __PACKAGE__->new();
   my $id = $o->{id};
'
Not a HASH reference at -e line 9.
1
On

One way to do this, is by using "inside-out objects", where the object is just a blessed simple scalar, and the data is stored separately. See, for instance, Class::STD