http://www.perlmonks.org?node_id=996852

sathish_cudd has asked for the wisdom of the Perl Monks concerning the following question:

Hey Guys, I am trying to edit the object parse. But am not successful, Please provide your thoughts and inputs. This is my First class
#!/usr/bin/perl use strict; use warnings; use Data::Dumper; package First; use Params::Validate qw(validate :types); our @EXPORT = qw(teller); our %params = ( 'A' => {'TYPE' => SCALAR}, 'B' => {'TYPE' => SCALAR} ); sub new { my ($class, @parameters) = @_; my $validate = {%params}; my $self = {validate(@parameters, $validate)}; return bless ($self,$class); } sub teller(){ my ($a) = shift; print Data::Dumper->Dump([$a]),"\n"; return 0; }
and my main program,
#!/usr/bin/perl use strict; use warnings; use First qw(teller); my $obj = new First('A' => 'red','B'=>'green'); for (1..3 ) { # print ref($obj),"\n"; $obj->teller('Called', 'A' => 'Yellow'); }
I am expecting to see the A value as Yellow, but it red. Can some one tell how to change the values of object? Please ignore the for loop. its just for testing.

Replies are listed 'Best First'.
Re: Modify the Object
by Athanasius (Archbishop) on Oct 02, 2012 at 13:02 UTC
    Can some one tell how to change the values of object?

    The usual way is to provide an accessor method in the First package:

    sub access_A { my ($self, $new_a) = @_; $self->{A} = $new_a if defined $new_a; return $self->{A}; }

    Then you can call this method in the main program as follows:

    my $obj = new First('A' => 'red', 'B' => 'green'); print "Here, A's colour is ", $obj->access_A(), "\n"; $obj->access_A('yellow'); $obj->teller();

    which will output:

    Here, A's colour is red $VAR1 = bless( { 'A' => 'yellow', 'B' => 'green' }, 'First' );

    By the way, in the definition of sub teller there should not be any parentheses after the method name. The parentheses create a prototype, saying that the sub takes no arguments — which is unnecessary, and, in this case, incorrect.

    Hope that helps,

    Update: Added defined to the test in sub access_A, to solve the problem identified by tobyink, below.

    Athanasius <°(((><contra mundum

      Your example accessor has a problem:

      package Local::Class; sub new { my $class = shift; bless +{ A=>'default' }; } sub access_A { my ($self, $new_a) = @_; $self->{A} = $new_a if $new_a; return $self->{A}; } package main; use 5.010; my $obj = Local::Class->new; $obj->access_A(1); say $obj->access_A; # says 1 $obj->access_A(2); say $obj->access_A; # says 2 $obj->access_A(0); say $obj->access_A; # says 2 !!!

      A better way of writing that accessor would have been:

      sub access_A { my $self = shift; $self->{A} = shift if @_; return $self->{A}; }

      (Or even better, use Moose so that you don't need to worry about writing accessors.)

      perl -E'sub Monkey::do{say$_,for@_,do{($monkey=[caller(0)]->[3])=~s{::}{ }and$monkey}}"Monkey say"->Monkey::do'

      Your amendment is fine but I prefer the idiom tobyink showed. It's terse and lends itself to simple flow validation–

      # use Carp; sub access_A { my $self = shift; $self->{A} = shift if @_; croak "Too many arguments to access_A" if @_; $self->{A}; }
Re: Modify the Object
by 2teez (Vicar) on Oct 02, 2012 at 13:13 UTC

    Just a cent addition to what has been said:
    Please, you don't EXPORT any subroutine from module that is written to be OO.
    So, your usage should be:

    package First; use Params::Validate qw(validate :types); sub new{ ... } ...
    And to use the module, then you use
    use strict; use warnings; use First; ...
    check these: perlmod, perlmodlib, etc

    If you tell me, I'll forget.
    If you show me, I'll remember.
    if you involve me, I'll understand.
    --- Author unknown to me