multiple packages/classes in one file

I

ioneabu

I was trying to put together a simple example of a couple of classes in
a single file in order to experiment with basic perl OO concepts. My
example did not work, so I tried a more basic example right out of the
Perl Cookbook:


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

package Alpha;
$name = "first";

package Omega;
$name = "last";

package main;
print "Alpha is $Alpha::name, Omega is $Omega::name.\n";


I only added the first three lines to make it a proper executable
program. Result of trying to execute:

Global symbol "$name" requires explicit package name at ./test3.pl line
7.
Global symbol "$name" requires explicit package name at ./test3.pl line
10.
Execution of ./test3.pl aborted due to compilation errors.

My class example, which suffers from the same problem is the following:


#!/usr/bin/perl

use warnings;
use strict;

my $a = one->new;
my $b = two->new;

print $a->get_member,"\n";
print $b->get_member,"\n";

#class one
package one;
sub new
{
my $class = shift;
my $self = {};
bless($self, $class);
return $self;
}
sub set_member
{
$member = shift; #not sure if this is right
}
sub get_member
{
return $member;
}
$member = 10;

#class two
package two;
sub new
{
my $class = shift;
my $self = {};
bless($self, $class);
return $self;
}
sub set_member
{
$member = shift;
}
sub get_member
{
return $member;
}
$member = 20;

(Preview in Google messed up some of my indenting. If it appears that
I did not indent, it is not how I typed in my code.)
 
I

ioneabu

Sorry for the indenting problem caused by Google. I even tried
changing my tabs to spaces and it still removed them. I am considering
going back to my old usenet service.

wana
 
G

Gunnar Hjalmarsson

I was trying to put together a simple example of a couple of classes in
a single file in order to experiment with basic perl OO concepts. My
example did not work, so I tried a more basic example right out of the
Perl Cookbook:

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

package Alpha;
$name = "first";

The Cookbook or not, since strictures are enabled, you need to either
declare variables or use their fully qualified names:

our $name = "first";
package Omega;
$name = "last";

our $name = "last";
 
I

ioneabu

The Cookbook or not, since strictures are enabled, you need to either
declare variables or use their fully qualified names:

our $name = "first";


our $name = "last";

Thanks! I did some reading on 'our' and it makes sense. It makes it
so you can use globals under strict and not just lexicals. By global,
this means global to the package that our is used in. I fixed up my OO
example:

#!/usr/bin/perl

use warnings;
use strict;

my $a = one->new;
my $b = two->new;

$a->set_member(11);
$b->set_member(21);
print $a->get_member,"\n";
print $b->get_member,"\n";

#class one
package one;
our $member;
sub new
{
my $class = shift;
my $self = {};
$member = 10;
bless($self, $class);
return $self;
}
sub set_member
{
my $self = shift;
$member = shift;
}
sub get_member
{
return $member;
}

#class two
package two;
our $member;
sub new
{
my $class = shift;
my $self = {};
$member = 20;
bless($self, $class);
return $self;
}
sub set_member
{
my $self = shift;
$member = shift;
}
sub get_member
{
return $member;
}


I found that if I set the value for the $member variable where it is
declared, I got an error for trying to print an uninitialized value.
When I set the default value in the constructor (assuming I don't use
set_member to change it) it works fine. I was wondering why it didn't
work, although I do see the sense in setting an object's default values
in the constructor. Here is the erroneous code I had before:

....
#class one
package one;
our $member = 10; #Perl didn't accept me setting my default value here.
sub new
{
my $class = shift;
my $self = {};
bless($self, $class);
return $self;
}
....

wana (if my indenting disappears, it's Google!)
 
T

Todd W

Thanks! I did some reading on 'our' and it makes sense. It makes it
so you can use globals under strict and not just lexicals. By global,
this means global to the package that our is used in. I fixed up my OO
example:

#!/usr/bin/perl

use warnings;
use strict;

my $a = one->new;
my $b = two->new;

$a->set_member(11);
$b->set_member(21);
print $a->get_member,"\n";
print $b->get_member,"\n";

#class one
package one;
our $member;
sub new
{
my $class = shift;
my $self = {};
$member = 10;
bless($self, $class);
return $self;
}
sub set_member
{
my $self = shift;
$member = shift;
}
sub get_member
{
return $member;
}

#class two
package two;
our $member;
sub new
{
my $class = shift;
my $self = {};
$member = 20;
bless($self, $class);
return $self;
}
sub set_member
{
my $self = shift;
$member = shift;
}
sub get_member
{
return $member;
}

Please remember that your $member vaiable is class data and not instance
data, So technically, your code is not object oriented at all. note:

[trwww@waveright misc]$ cat oo.pl
use warnings;
use strict;

package one;

# this is fine, dont know why you had trouble
our $member = 10;

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

sub get_member { $member }

sub set_member {
my $self = shift; # heres your object
$member = $_[0] if ( @_ );
}

package main;

print('access via package [', $one::member, "]\n");
my $first_one = one->new;
print('access via $first_one [', $first_one->get_member, "]\n");
my $second_one = one->new;
print("changing class data via \$second_one...\n");
$second_one->set_member( 55 );
print('access via $first_one [', $first_one->get_member, "]\n");

[trwww@waveright misc]$ perl oo.pl
access via package [10]
access via $first_one [10]
changing class data via $second_one...
access via $first_one [55]

To be object oriented, you want each object to maintain seperate data for
member. You accomplish that by using your bless()ed variable. This variable
is automatically set as the first argument in your subroutine's argument
list:

[trwww@waveright misc]$ cat oo.pl
use warnings;
use strict;

package one;

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

sub get_member {
my $self = shift; # heres your object
$self->{member};
}

sub set_member {
my $self = shift; # heres your object
$self->{member} = $_[0] if ( @_ );
}

package main;

my $first = one->new( member => 22 );
my $second = one->new( member => 55 );

print( 'member in $first [', $first->get_member, "]\n" );
print( 'member is $second [', $second->get_member, "]\n" );
print( "changing data in \$first\n" );
$first->set_member( 20 );
print( 'member in $first [', $first->get_member, "]\n" );
print( 'member is $second [', $second->get_member, "]\n" );
[trwww@waveright misc]$ perl oo.pl
member in $first [22]
member is $second [55]
changing data in $first
member in $first [20]
member is $second [55]

In languages like C++ and VB.NET, variable names are usually assumed to be
instance data unless explicitly declared otherwise, for example:

oVar = new Object
means the same thing as
this.oVar = new Object
I found that if I set the value for the $member variable where it is
declared, I got an error for trying to print an uninitialized value.
When I set the default value in the constructor (assuming I don't use
set_member to change it) it works fine. I was wondering why it didn't
work, although I do see the sense in setting an object's default values
in the constructor. Here is the erroneous code I had before:

To reiterate, you havent as yet set any object's value. If perl said you
were trying to print an uninitialized value, I'd probably take any bet you'd
be willing to make that you are. As I showed above, what you are trying to
do below is perfectly legal.
...
#class one
package one;
our $member = 10; #Perl didn't accept me setting my default value here.
sub new
{
my $class = shift;
my $self = {};
bless($self, $class);
return $self;
}
...

Have fun,

Todd W.
 
I

ioneabu

Todd W wrote:
....
Please remember that your $member vaiable is class data and not instance
data, So technically, your code is not object oriented at all. note:
....

Thanks, I just realized that this morning with a little more
experimentation. I thought I had Perl OO figured out and then realized
that my $member variable could not possibly be unique to individual
objects the way I did it.

So, it looks like all member data must be stored in or referred to by
the variable (almost always a hash) that is blessed into the class.
This is somewhat alien to a C++, Java programmer, but not too hard
understand.

Thanks again!

wana
 
T

Todd W

Todd W wrote:
...
...

Thanks, I just realized that this morning with a little more
experimentation. I thought I had Perl OO figured out and then realized
that my $member variable could not possibly be unique to individual
objects the way I did it.


Just remember that your bless()ed refrence is your object and you do have it
figured out.
So, it looks like all member data must be stored in or referred to by
the variable (almost always a hash) that is blessed into the class.
This is somewhat alien to a C++, Java programmer, but not too hard
understand.

Right. I like it because the syntax makes it easy to determine if you have
an object property or if you are working with some other variable. To do the
same in other languages I have written in, I always explicitly use the
"this" pointer.
Thanks again!

You bet

Todd W.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,969
Messages
2,570,161
Members
46,705
Latest member
Stefkari24

Latest Threads

Top