Assume the following code:
package Thing; sub new { my $this=shift; bless {@_},$this; } sub name { my $this=shift; if (@_) { $this->{_name}=shift; } return $this->{_name}; }
Now suppose we created an object this way:
my $o=Thing->new(); $o->name('Harold');
Good. We could also quickly create the same thing: either
my $o=Thing->new(_name=>'Harold');
Of course, I allowed the attributes to be passed in the constructor to allow the "friendly" classes to create objects more fully. It can also allow an operator of type clone with the following code:
my $o=Thing->new(%$otherthing);
This is good and good. I understand the need to hide attributes behind methods that allow validation, etc.
$o->name;
But this does not make it easy to manipulate an attribute based on it, for example:
$o->{_name}=~s/old/ry/;
One option is as follows:
# Cumbersome, not syntactically sweet my $n=$o->name; $n=~s/old/ry/; $o->name($n);
Another potential is the following method:
sub Name :lvalue {
Now I can do the following:
$o->Name=~s/old/ry/;
So my question is ... is it above "kosher"? Or is it a bad form to expose an attribute this way? I mean, this removes any validation that can be found in the name method. For example, if the method “name” forcibly put the first letter and a lower case letter into it, “Name” (capital “N”) bypasses this and forces the user of this class to protect themselves when using it.
So, if the “Name” lvalue method is not exactly “kosher”, are there any established ways to do such things?
I considered (but I am dizzy considering) things as attached scalars, as attributes. Of course, this could be the way to go.
Also, maybe there might be overloads that might help?
Or should I create replacement methods in the spirit (if it works):
sub replace_name { my $this=shift; my $repl=shift; my $new=shift; $this->{_name}=~s/$repl/$new/; } ... $o->replace_name(qr/old/,'ry');
Thanks in advance ... and mind you, I'm not very good at the Perl OOP brand, although I'm pretty good at OOP.
Additional info: I guess I could get very creative with my interface ... here is an idea I was messing around with, but I think it shows that there really are no boundaries:
sub name { my $this=shift; if (@_) { my $first=shift; if (ref($first) eq 'Regexp') { my $second=shift; $this->{_name}=~s/$first/$second/; } else { $this->{_name}=$first; } } return $this->{_name}; }
Now I can either set the name attribute with
$o->name('Fred');
or i can manipulate it with
$o->name(qr/old/,'ry');
This still doesn't allow things like $ o-> name. = 'Jr.'; but it’s not too difficult to add. Heck, I could let pass calllback functions, right?