Re: Module questions (perhaps a module creation mini-tutorial)

From: Jeff 'japhy' Pinyan (japhy_at_perlmonk.org)
Date: 03/25/05


Date: Fri, 25 Mar 2005 14:23:22 -0500 (EST)
To: Peter Rabbitson <rabbit@rabbit.us>

On Mar 25, Peter Rabbitson said:

> package CalcTest;
>
> use warnings;
> use strict;
>
> my @collect;

This is suspect. You shouldn't be using this array. You should be
storing data in your object.

> 1;

It's probably safer to put this at the very end of your module, just in
case you have other code (non-subroutine code) that could possibly return
false.

> sub new {
>
> my $class = shift;
>
> my $self = {};
>
> @collect = (0,0,0);
>
> bless $self, $class;
>
> return $self;
> }

How about:

   sub new {
     my $class = shift;
     my $self = [ 0, 0, 0 ];
     bless $self, $class;
     return $self;
   }

Now instead of using an outside array, each object will have its OWN three
numbers.

> sub add {
>
> print (shift @_);

The first argument to ANY method is the class or object that invoked the
method. $_[0] is the object in this case.

> if ( (scalar @_) != 3) {
> return undef;
> }
>
> my ($var0, $var1, $var2) = @_;
>
> $collect[0] += $var0;
> $collect[1] += $var1;
> $collect[2] += $var2;
>
> return 1;
> }

How about:

   sub add {
     my $self = shift;
     return unless @_ == 3;
     $self->[0] += shift;
     $self->[1] += shift;
     $self->[2] += shift;
     return 1;
   }

That uses the object $self, which is an array reference, and adds one
argument to each element of @$self in turn.

> sub result {
>
> return @collect;
> }

Here, it'd be:

   sub result {
     my $self = shift;
     return @$self;
   }

> #### main perl program (test.pl)
>
> use warnings;
> use strict;
>
> use CalcTest;
>
> my $calc = CalcTest->new();
>
> print "error\n\n" unless $calc->add (3, 4, 5);
>
> print "error\n\n" unless $calc->add (1, 2, 3);
>
> print join (' * ',$calc->result);
> print "\n\n";
>
> exit 0;

The interface to the module hasn't changed at all, so the code above
should still work.

> 1. Everytime I call one of the subroutines (methods I believe they are
> called?) I get a hash in $_[0] with only one value - the string name of the
> package I am calling. What defines the contents of this hash? Is it always
> just this single value pair or there might be additional values? If yes -
> what kind? (A reference towards *clear* documentation would be best).

You were misunderstanding the output of printing the object. It printed
something like

   CalcTest=HASH(0x....)

That's what an object looks like when you print it. Class=TYPE(ADDR).

You typically STORE information in the object. Your code was ignoring it
entirely. There was no need for your code to be "object-oriented" at all.

> 2. The idea of blessing... I understand the idea, I don't understand the
> reason. Why does bless need an empty hash intialized for it to bless it?
> Isn't blessing completely symbolic? Or I actually might put something in
> \%self ? If I do - what does this give me?

Blessing a reference tells Perl that the reference is now an object of a
specific class, and can invoke methods of that class with the $obj->method
syntax.

> 3. The usage of my in a package - here and there I see clues that 'my' does
> behave differently when used in a module - is this true? Is it correct do
> declare a package-wide @collect and have subroutines work on this
> semi-global variable (global from the package point of view), so I can get
> results that stack-up - the addition in the above example, or the
> accumulation like in Text::CSV where you keep pushing data in, and then you
> wrap a string... you probably see where I am going.

You were using @collect poorly. With your code, you couldn't have TWO
instances of a CalcTest. Any work the first instance did would be erased
when the second instance is created, and after that, both instances would
always return the same results.

> 4. If I don't define an explicit return value for a sub - is it always undef
> (like I would expect) or the package occasionally might decide to assign
> something as a return value?

If there is no explicit return value for a function, it returns the LAST
thing it evaluated.

As far as documentation goes, please read

   perldoc perlboot

-- 
Jeff "japhy" Pinyan         %  How can we ever be the sold short or
RPI Acacia Brother #734     %  the cheated, we who for every service
http://japhy.perlmonk.org/  %  have long ago been overpaid?
http://www.perlmonks.org/   %    -- Meister Eckhart


Relevant Pages

  • Re: Sharing variables between modules
    ... use strict; ... use warnings; ... # Note that this must also come *before* the use Foo line. ... package Foo; ...
    (comp.lang.perl.misc)
  • Re: matching password problem
    ... and turn on warnings. ... You don't need to store the usernames and passwords in arrays in your code, because you only need to look at ONE username and ONE password at a time. ... And if you DID want to store them, you should use a hash, not an array. ... use strict; use warnings; ...
    (perl.beginners)
  • Re: creating named subroutines in a loop
    ... package Person; ... use strict; ... use warnings; ... Sinan Unur ...
    (comp.lang.perl.misc)
  • Re: How do I convert an array of x-y coordiates in to a image?
    ... You just need to get the dimensions of your array ... use warnings; ... use strict; ... # a random color image using GD IO ...
    (comp.lang.perl.misc)
  • Re: Dynamic object creation
    ... Thx Sinan Unur, ... use strict; ... use warnings; ... package X::A; ...
    (comp.lang.perl.misc)