@Chewbacca said:
Anyone familiar with Perl will know that a class, or an object, or whatever you might call it, is essentially a glorified hashref, or "a pointer to an associative array".
False. A perl object *can be* a glorified hash ref. It can also be a glorified array ref, a glorified scalar ref, a glorified code ref, or a glorified handle ref.. The language just requires that it be a ref of some kind, as only refs can be glorified. (At least, if by 'glorified', you mean 'blessed'.)
In the past few years, someone had the bright idea to tie this flexibility together with lexical variables. You have your constructor generate a scalar ref (as scalars take up less memory than all of the other things we can reference), and then make the real object in one or more lexical hashes, using the address of the scalar as the hash key. Bless the scalar ref, and return it as your object.
With this mechanism, the only way to access the guts of the object directly is to write code in the file that defines the object. People who are merely using your class can't touch it. The only thing they can illicitly access is the scalar value - and this scheme doesn't even use that.
You pay a slight performance penalty, because all of your accesses have to be through accessor functions, rather than simply pulling data out of the hash. However, it allows you to detect scenarios like the above - at least, so long as you don't allow them to pass in the rule structure as a nested structure like above. Instead, you have your rule list passed in as an array of pairs to the initializer, and if it sees a key that has already been defined, it can warn of the problem. You may also get a very slight memory benefit - scalars take up less space than hashes, and under this scheme, you get a constant number of hashes, rather than one hash per object.
Scalar::Util is helpful for this, but not absolutely required. Same for Class::Std. (Note: while the technique works all the way back to perl 5.6.1, Class::Std has a dependency that requires perl 5.8.0 or newer. Class::Std only gives you easier constructors/destructors - while it's nice to write less code, if you're stuck before 5.8.x, it's probably easier to write a little more code than to get everything ported to a newer perl. I mean, if you were going to upgrade perl at some point, you'd have done it already, right?)
There is, of course, some legibility danger here - using the 'inside-out' objects described above, it is possible to make a coordinate object that has x,y, and z values, and then subclass it, and have the subclass have a different set of x, y, and z values, while also having the first set. One could repeat this idiocy any number of times. And, yes, this is a story I'm not able to go into here just yet. At this point, I'm just wanting to advise: don't do that. Overloading the member names of an inside-out object is just asking for problems.