LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Programming (http://www.linuxquestions.org/questions/programming-9/)
-   -   Perl OO: First attempt, why doesn't this code work? (http://www.linuxquestions.org/questions/programming-9/perl-oo-first-attempt-why-doesnt-this-code-work-930923/)

SparceMatrix 02-23-2012 02:29 PM

Perl OO: First attempt, why doesn't this code work?
 
I have been through O'Reilly's "Learning Perl References, Objects and Modules", 1st edition. I thought I had a pretty good handle on it, but I am stumped by this first attempt. Why do I keep getting the "blessed scalar reference as a string" (section 9.8) back?

Code:

#!/usr/bin/perl -w
use strict;
{
        package TESTOO;

        sub new {
                my $class = shift;
                my $object = { };
                bless $object, $class;
        }

        sub sub_A {
                my $self = $_[0];
                if ($_[1]) {
                        $self->{HASH_1} = $_[1];
                } else {
                        $self->{HASH_1};
                }
        }

        sub sub_B {
                my $self = $_[0];
                print "This is a test.\n";
        }

}

my $test = TESTOO->new;
$test->sub_A("THIS IS A TEST");

print "Here is the hash entry at HASH_1:  $test->sub_A\n";
print "Here is method part_B: $test->sub_B\n";

I expect,

Code:

Here is the hash entry at HASH_1:  THIS IS A TEST
Here is method part_B: This is a test.

But I am getting,

Code:

Here is the hash entry at HASH_1:  TESTOO=HASH(0x8320d54)->sub_A
Here is method part_B: TESTOO=HASH(0x8320d54)->sub_B

What am I missing?

theNbomr 02-23-2012 03:56 PM

Perhaps this is more like what you want:
Code:

#!/usr/bin/perl -w
use strict;
{
        package TESTOO;

        sub new {
                my $class = shift;
                my $object = { };
                bless $object, $class;
        }

        sub sub_A {
                my $self = $_[0];
                if ($_[1]) {
                        $self->{HASH_1} = $_[1];
                } else {
                        return $self->{HASH_1};
                }
        }

        sub sub_B {
                my $self = $_[0];
                print "This is a test.\n";
        }

}

my $test = TESTOO->new;
$test->sub_A("THIS IS A TEST");

print "Here is the hash entry at HASH_1: ", $test->sub_A, "\n";
print "Here is method part_B: "; $test->sub_B,"\n";

It is hard to see what you are expecting with the call to sub_B, since it doesn't return anything in particular.


--- rod.

sundialsvcs 02-23-2012 05:09 PM

You do not need, and ought not have, the enclosing braces { ... }.

Customarily, you would put the package in (say...) TESTOO.pm, with the package statement as the first line and always ending the file with this:
Code:

1;
... because every .pm "must return 'true'."

However, you can have more than one package statement in the same file ... (Perl is very agreeable) ... for example: package main;

... and you could, if you wanted to, just write the test-code right there in the same package.

One more thing: do this... use strict; use warnings;.

I suggest that you get to know http://www.perlmonks.org.

Funny, Perl was one of the most recent languages that I picked-up, but, danged if I haven't found myself using it fairly constantly ever since. It is an extremely practical and pragmatic, "just move the dammed freight," language, of extraordinary strength and ability. Perhaps most importantly, its battle-tested CPAN library goes on forever...

SparceMatrix 02-24-2012 12:42 PM

theNbomr, it turns out the only thing that was causing my basic problem was the print commands, when I took the object reference entries out of the quotes, then I started getting the results I wanted. Except, I wasn't getting the print command from sub_B. Here is what I am getting now:

Code:

#!/usr/bin/perl -w
use strict;
use warnings;

package TESTOO;

sub new {
        my $class = shift;
        my $object = { };
        bless $object, $class;
}

sub sub_A {
        my $self = $_[0];
        if ($_[1]) {
                $self->{HASH_1} = $_[1];
        } else {
                $self->{HASH_1};
        }
}

sub sub_B {
        print "This is a test.\n";
}

my $test = TESTOO->new;
$test->sub_A("THIS IS A TEST");

print "Here is the hash entry at HASH_1: ",  $test->sub_A,"\n";
print "Here is method part_B: ", $test->sub_B, "\n";

This yields,

Code:

Here is the hash entry at HASH_1: THIS IS A TEST
This is a test.
Here is method part_B: 1

At least I am getting my string loaded and returned properly in $test->sub_A.

So why am I getting the "This is a test." back in line two, and why isn't $test->sub_B giving me the print command at the printed string instead of the simple "1"? (Indicating a successfully completed command or something, I don't know)

sundialsvcs, yes I see now that the brackets around the package part is not necessary, I tried it without and it works fine. And yes, my project includes modules.

Cedrik 02-24-2012 01:03 PM

On last line, print evaluates terms in list context
Better use:
Code:

print "Here is the hash entry at HASH_1: ",  $test->sub_A,"\n";
print "Here is method part_B: ";
$test->sub_B;

Also I think you should explicitly return $object in sub new constructor and explicitly return $self->{HASH_1} in sub_A method

SparceMatrix 02-24-2012 01:32 PM

Problem solved
 
Yes, maybe explicitly returning from a method is best. And yes, I see how print changes the way a sub works inside the quotes.

Here is an improvement showing better understanding,

Code:

#!/usr/bin/perl -w
use strict;
use warnings;

package TESTOO;

sub new {
        my $class = shift;
        my $object = { };
        bless $object, $class;
        return $object;
}

sub sub_B {
        my $self = $_[0];
        if ($self) {
                ref $self ? $self = "OBJECT METHOD" : $self ;
        } else {
                $self = "NOT AN OBJECT METHOD\n";
        }
        print "From sub_B: $self\n";
}

my $test = TESTOO->new;

TESTOO->sub_B;
$test->sub_B;
sub_B;

This yields,

Code:

Useless use of private variable in void context at TESTOO.pl line ...
From sub_B: TESTOO
From sub_B: OBJECT METHOD
From sub_B: NOT AN OBJECT METHOD

I don't understand the "private variable in void context" warning, but I think I am on track.

Cedrik 02-24-2012 02:11 PM

Instead of
Code:

ref $self ? $self = "OBJECT METHOD" : $self ;
I would do:
Code:

$self = "OBJECT METHOD" if ref $self;

SparceMatrix 02-24-2012 02:48 PM

Yes, that's better. Thanks.


All times are GMT -5. The time now is 10:54 AM.