Re: Ironclad protection of instance data
by adrianh (Chancellor) on Jul 03, 2004 at 17:29 UTC
|
| [reply] |
|
|
Interesting link, thanks. But I must admit I have no idea what's going on.
sub set_phrase {
my $self = shift;
my $phrase = shift;
$phrase {$self} = $phrase;
}
sub get_phrase {
my $self = shift;
return $phrase {$self};
}
What does $phrase {$self} do? | [reply] [d/l] |
|
|
What does $phrase {$self} do?
It uses the stringified reference at $self as the key for a lexical hash. The hash is unreachable outside of the module, but is shared between all the instances of that object, so you have to key it on something unique. Using the stringified reference is a convenient way to do that.
Update: just to clarify a bit what I mean by stringified reference:
$ perl -le 'my $self = {}; print $self'
HASH(0x814cc20)
Something like that would be used as the hash key. Since that contains a memory location, it will be unique (unless something Very Bad happens). | [reply] [d/l] [select] |
|
|
Re: Ironclad protection of instance data
by dws (Chancellor) on Jul 03, 2004 at 17:47 UTC
|
For the first time, I am going to enforce strict OO standards ...
When I hear this, I cringe. Nine times out of ten, the result will be barely usable, usually because the author's vision for their precious class library hasn't been broad enough to encompass the variety of problems that people might use the class library to solve, and sometimes because the resulting class library is too constrained. (Consider the standard Java classes. Need to extend String? Sorry, out of luck.)
Before you go too far down the "enforce" road, consider the "enable" road. It's a friendlier road, even if it can be a bit more chaotic. If you prefer to stick with the former path, consider switching to a language that supports enforcement with less convolution than Perl requires. Or treat the whole thing as an experiment.
| [reply] |
|
|
Well, the reason I'm doing this is to ensure that subclassing will work painlessly. A subclass will automatically inherrit the accessors for the class data, and some of my instance accessors are somewhat complex, and so I want to ensure that even the objects themselves retrieve data via the accessors rather than directly. If the accessor logic changes, then any method that does direct access may break. These classes are being written by a number of developers which is why I want to ensure that data can't be accessed directly, by accident or otherwise. :)
| [reply] |
|
|
| [reply] [d/l] |
Re: Ironclad protection of instance data
by Arunbear (Prior) on Jul 03, 2004 at 17:52 UTC
|
You can use a blessed subroutine reference technique:
package My::Class;
use strict;
use warnings;
{
# hide from the rest of the class
my %CLASSDATA = ( foo => 1, bar => 2, baz => 3 );
# install generic accessor/mutator methods
no strict 'refs';
for my $key(keys %CLASSDATA) {
*$key = sub { shift;
$CLASSDATA{$key} = shift if @_;
return $CLASSDATA{$key};
};
}
}
my @ATTRIBUTES = qw/name alias race/;
sub new
{
my ($class, %args) = @_;
my %data = (name => 'aragorn', alias => 'elessar', race => 'man',
+%args);
my $self = sub {
my $field = shift;
if(@_) { $data{$field} = shift }
return $data{$field};
};
bless $self, $class;
}
for my $attr (@ATTRIBUTES) {
no strict 'refs';
*$attr = sub {
my $self = shift;
return $self->($attr, @_);
};
}
| [reply] [d/l] |
Re: Ironclad protection of instance data
by stvn (Monsignor) on Jul 04, 2004 at 04:13 UTC
|
Nothing can be truely ironclad since you are using perl and no matter what you do, someone could probably get around it (although some solutions require walking the op-tree which is just silly).
But seriously, I would have to agree with dws in that you may be restricting yourself too much. I have dealt with this issue myself in the past, and have created a module (Devel::StrictObjectHash) to solve it. I took a slightly different approach than you are suggestion, which is not to restrict access to instance data, but instead to verify that it is not accessed incorrectly.
Devel::StrictObjectHash allows you to use hash-ref based Perl OO and with a few lines of up-front configuration (and no extra code in your classes) check that your instance data is protected from misuse during development and testing. Once you are satisfied, you can remove the configuration and allow your code to run unhindered. It allows the 3 common styles of access (public, protected and private) and is flexible with hash-key naming conventions as well. If you are interested and/or have any questions let me know and I will be happy to help.
| [reply] |
|
|
This sounds like a Murphy's Law variant: If there is more than one day to do it, and one of those ways is wrong, then Perl will make it possible.
| [reply] |
|
|
Kind of puts me in mind of an situation back in the '80s when Volvo decided to make the sidelights on their cars be on whenever the ignition was on.
They did this as a consequence of a law change in Sweden that required all vehicles to switch their sidelights on when moving. That law came about as a consequence of the fact that in a large part of Sweden has 3 months or so of 24 hour twilight/darkness each year, which meant that laws written in terms of "Vehicles shall switch their lights on 'at night' or 'after dark'" etc. were always open to legal (mis)interpretation.
Later, when drivers in other countries drove their Volvo's around during the daytime, (besides getting perpetually flashed "Your lights are on idiot!", by other road users taking the p***:), they found themselves in court if a sidelight bulb blew--EVEN IF IT WAS BRIGHT SUNLIGHT.
Laws, like rules, are written to achieve a particular end. In this case, the lights are there to ensure the vehicle can be seen in low-light visibility.
The law is an ass because often as not, there is no room allowed for interpretation. To be seen at night, the vehicle must have lights. To do any good, the lights must work. If they don't work, an offense has been commited.
If the working light would not have affected the visibility of the vehicle, should the errent owner be prosecuted?
Examine what is said, not who speaks.
"Efficiency is intelligent laziness." -David Dunham
"Think for yourself!" - Abigail
"Memory, processor, disk in that order on the hardware side. Algorithm, algoritm, algorithm on the code side." - tachyon
| [reply] [d/l] |
Re: Ironclad protection of instance data
by water (Deacon) on Jul 04, 2004 at 19:04 UTC
|
This is slightly off-topic, as your post is about strong encapsulation. Nonetheless, do take a look at Class::MethodMaker to help reduce the drudgery of
setting up the setters & getters. Perhaps you could subclass C:MM somehow if you really really need to lock up all the doors tight (rather than just latching the doors, as suggested by most of the previous respondents to your post).
water water everywhere | [reply] |