Learning Object Oriented Programming (newbie)

N

Nene

This is my first attempt to OOP, here is my package:

#####

package Learn;

use strict;

sub new {

my $class = shift;
my $learn_oop = {};
return bless $learn_oop, $class;
}

sub set_farm {
my $learn_oop = shift;
my $farm = shift;
$learn_oop->{farm} = $farm;
}

sub get_farm {
my $learn_oop = shift;
return $learn_oop->{farm};
}

sub set_port {
my $learn_oop = shift;
my $port = shift;
$learn_oop->{port} = $port;
}

sub get_port {
my $learn_oop = shift;
return $learn_oop->{port};
}


sub print_variables {
print "Do something with $learn_oop->{farm} and with $learn_oop-
}

#####################

This is my perl script

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


my $farm = "WEB";
my $port = "1234";
my $status = "enabled";

my $test = Learn->new();
$test->set_farm($farm);
$test->set_port($port);

$test->print_varibles();


exit 0;
#######

My print_variables() method is not working, I get:
root@rsimioni-desktop:/home/control/perlstuff# ./quote.pl
Global symbol "$learn_oop" requires explicit package name at /usr/lib/
perl/5.10/Learn.pm line 36.
Global symbol "$learn_oop" requires explicit package name at /usr/lib/
perl/5.10/Learn.pm line 36.


Could somebody point me in the correct directions, thanks in
advance...
 
J

Jürgen Exner

Nene said:
This is my first attempt to OOP, here is my package: [snip-snap]
sub print_variables {
print "Do something with $learn_oop->{farm} and with $learn_oop-

These $learn_oop variables are not declared anywhere.

All those $learn_oop in the part that I snipped above are local and are
unknown outside of their own function definitions, in particular they
are unknown inside of print_variables()..

[...]
Global symbol "$learn_oop" requires explicit package name at /usr/lib/
perl/5.10/Learn.pm line 36.
Global symbol "$learn_oop" requires explicit package name at /usr/lib/
perl/5.10/Learn.pm line 36.

jue
 
R

Randal L. Schwartz

Nene> sub print_variables {

my $learn_oop = shift;

Nene> print "Do something with $learn_oop->{farm} and with
Nene> $learn_oop->{port}"; }

print "Just another Perl hacker,"; # the original
 
U

Uri Guttman

N> sub print_variables {
N> print "Do something with $learn_oop->{farm} and with $learn_oop-N> }

others pointed out you didn't declare $learn_oop and you didn't assign
it the object coming in from @_.

N> $test->print_varibles();

but that line will fail as well at runtime. the method here isn't
spelled the same as the one you created in the module.

uri
 
N

Nene

  N> sub print_variables {
  N> print "Do something with $learn_oop->{farm} and with $learn_oop-
  >> {port}";
  N> }

others pointed out you didn't declare $learn_oop and you didn't assign
it the object coming in from @_.


Mr. Schwartz is correct (thanks), I didn't declare $learn_oop.

  N> $test->print_varibles();

but that line will fail as well at runtime. the method here isn't
spelled the same as the one you created in the module.

Thank you, I see the typo, I fixed it and this simple OOP program not
works as expected.
I have another question. The $farm and $port belong to an environment
that I want to do something with down the road in the print_variable
method. But I have multiple kinds of $farm and $port variables that I
want to do something with at the same time.

Presently, I have $farm = WEB, and port = 1234. But I also have a
$farm = "ABC", port = "2345, and $farm = "XYZ" and $port = "9876" and
I want to apply those to the print_variables method as well. Can
somebody point me in the right direction?

 
N

Nene

You could store your data as a hash called "farms," and read/write it
like so:

sub setPortForFarm {
    my ($self, $port, $farm) = @_;
    $self->{'farms'}->{$farm} = $port;

}

sub portForFarm {
    my ($self, $farm) = @_;
    return $self->{'farms'}->{$farm};

}

You'd call the above with:

  my $farms = Farms->new();
  $farms->setPortForFarm(1234, 'WEB');
  $farms->setPortForFarm(8675309, 'Jenny');

For more about hashes of hashes, lists of lists, etc., see:

  perldoc perlreftut
  perldoc perldsc
  perldoc perllol

sherm--

Thanks Sherm.

I changed my .pm file and inputted what you suggested above:

sub setPortForFarm {
my ($self, $port, $farm) = @_;
$self->{'farms'}->{$farm} = $port;

}

sub portForFarm {
my ($self, $farm) = @_;
return $self->{'farms'}->{$farm};

In my perl script when I called the method portForFarm, it failed.
This is how I called it. I'm assuming since the
portForFarm had the return statement, it will print the data.
my $farms = Learn->new();
$farms->setPortForFarm(1234, 'WEB');
$farms->setPortForFarm(8675309, 'Jenny');
$farms->portForFarm();

exit 0;

I'm getting this error:
Use of uninitialized value $farm in hash element at /usr/lib/perl/5.10/
Learn.pm line 53.

Line 53 had this .... return $self->{'farms'}->{$farm};
 
P

Peter J. Holzer

I have another question. The $farm and $port belong to an environment
that I want to do something with down the road in the print_variable
method. But I have multiple kinds of $farm and $port variables that I
want to do something with at the same time.

Presently, I have $farm = WEB, and port = 1234. But I also have a
$farm = "ABC", port = "2345, and $farm = "XYZ" and $port = "9876" and
I want to apply those to the print_variables method as well. Can
somebody point me in the right direction?

I'm not sure whether I understand you correctly. Part of the problem is
that you named your class "Learn", and I have a hard time figuring out
what kind of thing a "Learn" might be which has a "farm" and a "port".

I am assuming that you want to have many "Learn" thingies, each of which
has exactly one farm and one port. Then your class is already ok and you
can just create many "Learn" objects with your new method:

my $learn_web = Learn->new();
$learn_web->set_farm('WEB');
$learn_web->set_port(1234);

my $learn_abc = Learn->new();
$learn_abc->set_farm('ABC');
$learn_abc->set_port(2345);

my $learn_xyz = Learn->new();
$learn_xyz->set_farm('AXYZ);
$learn_xyz->set_port(9876);

$learn_web->print_variables();
$learn_abc->print_variables();
$learn_xyz->print_variables();


or (almost equivalent):

my @learn_thingies;
my $learn_thing;

$learn_thing = Learn->new();
$learn_thing->set_farm('WEB');
$learn_thing->set_port(1234);
push @learn_thingies, @learn_thing;

$learn_thing = Learn->new();
$learn_thing->set_farm('ABC');
$learn_thing->set_port(2345);
push @learn_thingies, @learn_thing;

$learn_thing = Learn->new();
$learn_thing->set_farm('AXYZ);
$learn_thing->set_port(9876);
push @learn_thingies, @learn_thing;

$_->print_variables() for (@learn_thingies);

hp
 
N

Nene

I'm not sure whether I understand you correctly. Part of the problem is
that you named your class "Learn", and I have a hard time figuring out
what kind of thing a "Learn" might be which has a "farm" and a "port".

I named this package with the name Learn so I can let the readers of
this newsgroup to understand
that this is basically my first OOP in Perl and I'm basically learning
how to create a simple object
to hold data which I will do something with down the road.
I am assuming that you want to have many "Learn" thingies, each of which
has exactly one farm and one port. Then your class is already ok and you
can just create many "Learn" objects with your new method:

Basically a 'farm' is a VIP (ip address) and 'port' is a port that is
listening on the 'farm'.
I should have called this package IP::pORT for our readers to
understand.
 
N

Nene

Of course - you didn't pass an argument to it.

Thank you for clarifying, this is new to me. I'm enjoying the powers
of OOP.

  my $port = $farms->portForFarm('Jenny');


Why would you assume that? "print" ne "return". The latter returns a
value to the caller. So, after doing the above:

  print "$port\n";

Will print "8675309".



Right - $farm is uninitialized, because you didn't pass a value for the
argument when you wrote "$farms->portForFarm()".

I understand now, thanks.
 
S

Skye Shaw!@#$

This is my first attempt to OOP, here is my package:

#####

package Learn;

sub set_farm {
  my $learn_oop = shift;
  my $farm = shift;
  $learn_oop->{farm} = $farm;

}

sub get_farm {
  my $learn_oop = shift;
  return $learn_oop->{farm};

}

No need to define getters and setters for simple assignment. Save
those for the Java sweat shop :)
To be more in-line with Perl OOP try:

sub farm {
my $self = shift;
@_ ? $self->{farm} = shift : $self->farm;
}

See perldoc perltoot, Class::Accessor or, better yet, Object::Tiny.
 
U

Uri Guttman

SS> No need to define getters and setters for simple assignment. Save
SS> those for the Java sweat shop :)
SS> To be more in-line with Perl OOP try:

SS> sub farm {
SS> my $self = shift;
SS> @_ ? $self->{farm} = shift : $self->farm;
SS> }

have you tested that? really tested it? it will not do what you think it
does. classic abuse of ?:.

uri
 
S

Skye Shaw!@#$

  SS> No need to define getters and setters for simple assignment. Save
  SS> those for the Java sweat shop :)
  SS> To be more in-line with Perl OOP try:

  SS> sub farm {
  SS>   my $self = shift;
  SS>   @_ ? $self->{farm} = shift : $self->farm;
  SS> }

have you tested that? really tested it? it will not do what you think it
does. classic abuse of ?:.

What do I think it does?
 
U

Uri Guttman

SS> Well, aside from my typo: @_ ? $self->{farm} = shift : $self->{farm};
SS> how is it abuse?

well, it doesn't WORK. try it. really try it out. and it is abuse for
that reason.

uri
 
T

Ted Zlatanov

SS> Well, aside from my typo: @_ ? $self->{farm} = shift : $self->{farm};
SS> how is it abuse?

UG> well, it doesn't WORK. try it. really try it out. and it is abuse for
UG> that reason.

This line is near the top of my list for misguided
almost-getting-it-but-not-quite use of Perl. It's a mess of techniques
that may have made sense separately[1] but joined they create an unholy
union that will burn in my retinas for a while. Otherwise, it was OK.

Ted

[1] OP: you probably want "$self->{farm} = shift if @_;"
 
S

Skye Shaw!@#$

SS> Well, aside from my typo: @_ ? $self->{farm} = shift : $self->{farm};
SS> how is it abuse?

UG> well, it doesn't WORK. try it. really try it out. and it is abuse for
UG> that reason.

This line is near the top of my list for misguided
almost-getting-it-but-not-quite use of Perl. It's a mess of techniques
that may have made sense separately[1] but joined they create an unholy
union that will burn in my retinas for a while.

Please elaborate.
 
T

Ted Zlatanov

SS> Well, aside from my typo: @_ ? $self->{farm} = shift : $self->{farm};
SS> how is it abuse?UG> well, it doesn't WORK. try it. really try it out. and it is abuse for
UG> that reason.
This line is near the top of my list for misguided
almost-getting-it-but-not-quite use of Perl. It's a mess of techniques
that may have made sense separately[1] but joined they create an unholy
union that will burn in my retinas for a while.

SS> Please elaborate.

I gave the right way (if I understand correctly) to do what you're
trying to do. Here's how I proceeded.

You're mixing the ternary operator and assignments. You should not
assign *inside* a ternary operator (unless you want to confuse people),
but instead you should use the return value of the ternary operator.
This is a very, very important point and the main reason why the
original code was nasty. So:

$self->{farm} = @_ ? shift : $self->{farm};

....but that's redundant. You're using a hash key and entry twice, and
in my experience that's both unnecessary and dangerous because of typos.
So you can just say

$self->{farm} = shift if @_;

which will only happen if there is something to shift.

Ted
 
P

Peter Scott

SS> Well, aside from my typo: @_ ? $self->{farm} = shift :
$self->{farm}; SS> how is it abuse?UG> well, it doesn't WORK. try it. really try it out. and it is abuse
for UG> that reason.
This line is near the top of my list for misguided
almost-getting-it-but-not-quite use of Perl. It's a mess of
techniques that may have made sense separately[1] but joined they
create an unholy union that will burn in my retinas for a while.

SS> Please elaborate.

I gave the right way (if I understand correctly) to do what you're
trying to do. Here's how I proceeded.

You're mixing the ternary operator and assignments. You should not
assign *inside* a ternary operator (unless you want to confuse people),
but instead you should use the return value of the ternary operator.
This is a very, very important point and the main reason why the
original code was nasty. So:

$self->{farm} = @_ ? shift : $self->{farm};

...but that's redundant. You're using a hash key and entry twice, and
in my experience that's both unnecessary and dangerous because of typos.
So you can just say

$self->{farm} = shift if @_;

which will only happen if there is something to shift.

Stylistic concerns aside, the original poster's statement returns the
value of the attribute if no argument is passed to the method, a common
mixed getter/setter pattern. You'd need to add a return statement and
repeat the hash key anyway to get that behavior.
 
R

RedGrittyBrick

On Mon, 24 Jan 2011 12:29:54 -0500 "Uri Guttman"
SS> Well, aside from my typo: @_ ? $self->{farm} = shift :
$self->{farm}; SS> how is it abuse?UG> well, it doesn't WORK. try it. really try it out. and it is abuse
for UG> that reason.
This line is near the top of my list for misguided
almost-getting-it-but-not-quite use of Perl. It's a mess of
techniques that may have made sense separately[1] but joined they
create an unholy union that will burn in my retinas for a while.

SS> Please elaborate.

I gave the right way (if I understand correctly) to do what you're
trying to do. Here's how I proceeded.

You're mixing the ternary operator and assignments. You should not
assign *inside* a ternary operator (unless you want to confuse people),
but instead you should use the return value of the ternary operator.
This is a very, very important point and the main reason why the
original code was nasty. So:

$self->{farm} = @_ ? shift : $self->{farm};

...but that's redundant. You're using a hash key and entry twice, and
in my experience that's both unnecessary and dangerous because of typos.
So you can just say

$self->{farm} = shift if @_;

which will only happen if there is something to shift.

Stylistic concerns aside, the original poster's statement returns the
value of the attribute if no argument is passed to the method, a common
mixed getter/setter pattern. You'd need to add a return statement and
repeat the hash key anyway to get that behavior.


"If no return is found and if the last statement is an expression, its
value is returned. "

Perldoc perlsub
 
S

Skye Shaw!@#$

SS> Well, aside from my typo:  @_ ? $self->{farm} = shift : $self->{farm};
SS> how is it abuse?

UG> well, it doesn't WORK. try it. really try it out. and it is abuse for
UG> that reason.


This line is near the top of my list for misguided
almost-getting-it-but-not-quite use of Perl.  It's a mess of techniques
that may have made sense separately[1] but joined they create an unholy
union that will burn in my retinas for a while.

SS> Please elaborate.

I gave the right way (if I understand correctly) to do what you're
trying to do.  

I suggested that it would be more Perl-ish to rewrite:

sub get_farm {
my $learn_oop = shift;
return $learn_oop->{farm};

}

sub set_port {
my $learn_oop = shift;
my $port = shift;
$learn_oop->{port} = $port;

}

As:

sub farm {
my $self = shift;
@_ ? $self->{farm} = shift : $self->{farm};
}
You're mixing the ternary operator and assignments. You should not
assign *inside* a ternary operator (unless you want to confuse people),

Out of all the things one can pull off in Perl *that's* near the *top*
of your "...list for misguided
almost-getting-it-but-not-quite use of Perl."
 

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,769
Messages
2,569,580
Members
45,054
Latest member
TrimKetoBoost

Latest Threads

Top