in reply to regex transforms of object attributes

What's wrong with doing ...
$self->{'content'} =~ s/foo/bar/g;
... you know just don't use the get_set method.
update Added tested code.
Plankton@Chum_Bucket:~/perl/perlmonks> cat test.pl #!/usr/local/bin/perl -w use strict; package Test; sub new{ my( $class, $value ) = @_; return bless { content => $value }, $class; } 1; package main; my $thing = Test->new( 'empty' ); print $thing->{'content'} . "\n"; $thing->{'content'} = 'the quick brown fox'; print $thing->{'content'} . "\n"; $thing->{'content'} =~ s[\b(.)][\U$1]g; print $thing->{'content'} . "\n"; Plankton@Chum_Bucket:~/perl/perlmonks> ./test.pl empty the quick brown fox The Quick Brown Fox

Plankton: 1% Evil, 99% Hot Gas.

Replies are listed 'Best First'.
Re^2: regex transforms of object attributes
by BrowserUk (Patriarch) on Jun 19, 2004 at 01:01 UTC

    Nice tested code:)

    The problem with doing it that way is that you build a dependancy upon the implementation of the class. You have to know that the class is based upon a hash and that the data return by the $obj->content(); method is stored in the hash under the key name 'content'.

    If the implementation of the class changes for some reason, then it will require modification to every calling app also. That's what is meant by 'breaking encapsulation' or 'tight coupling'.

    Eg. If the class called by your test code was implemented this way, it will break your test.

    package Test; my %contents; sub new{ my( $class, $value ) = @_; my $self = bless \rand, $class; $contents{ $self } = $value; return $self; } sub content : lvalue { my( $self ) = shift; $contents{ $self }; } 1;

    Of course, if the content has to be verified then using an lvalue sub will also break, but that a different argument entirely:)


    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
      Well hopefully the implementation does not change. Yes I know famous last words. But lvalue is an experimental feature. That has its problems too.
      <update>It just occured to me that ...
      s/foo/bar/g;
      ... could take place in the class defintion. That wouldn't violate encapsulation would it? All one would have to do is add a method to the class. Something like ...
      sub s { my ( $obj, $pat, $sub ) = @_; $obj->{'content'} =~ s/$pat/$sub/g; }
      I wonder if it would be possible to use overload ... you know something like ...
      use overload "s" => \&s;

      Plankton: 1% Evil, 99% Hot Gas.
Re^2: regex transforms of object attributes
by belden (Friar) on Jun 18, 2004 at 23:43 UTC
    Violating encapsulation simply to avoid a transient variable seems like a poor trade to me.
      Really? Why you say that? The only "encapsulation" here is by convention. Perl does not have syntax to enforce information hiding. Does dealing with the attribute cause the attribute to become uncapsulated? I don't think so. The use of a variable to store the attribute does and has more potential for misuse in the code. Some thing that "encapsulation" is suppose to prevent.

      Plankton: 1% Evil, 99% Hot Gas.
        Who says that the $self->content variable stays a variable in the future? Dealing with the attribute doesn't cuase the attribute to become uncapsulated, but it does violate information hiding. An object has a published interface (the methods) which are more or less guaranteed to work. The upside is that when the author of the module/class feels there is a better way to implement things, she can do that without changes to the external interface.

        Of course you can use the attribute directly. No one is stopping you. It'll probably work just fine. Just don't get upset when it suddenly breaks your programs when you install a new version.

        Arjen

        This will not break due to changes in $obj's interface

        my $content = $obj->content(); $content =~ s/ome/thin/g; $obj->content( $content );

        This might

        $obj->{content} =~ s/ome/thin/g;

        The former uses the interface published by the module author. The latter relies on the internal workings of the object itself, and therefore violates the encapsulation of the object's data.

        The risk that comes with the latter form (your code is now tied to the current version of Whatever::Module, and that requirement is neither enforced nor documented) just doesn't seem worth the gain of avoiding creating $content.