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

Let me show you some of my code first ...
sub new { my $self = {}; $self->{BKG_IMAGE} = "image"; bless($self); return $self; } sub bkg_img { my $self = shift; $self->{BKG_IMAGE} = $_[0]; }
Later in the *same* package I want to get the value of $self->{BKG_IMG} in another sub and print it to STDOUT. For example (this is bad code):
sub print_html { print <<"HTML"; $self->{BKG_IMAGE} HTML } print_html();
All the code is in the same package (not main). Here's the kicker: Within main, a user can set the value $self->{BKG_IMAGE} by doing:
$p = new MyPackage; $p->bkg_img("whatever");
Whether or not, the value is set by the user before it's printed, I need to reference the current value of $self->{BKG_IMAGE} in that aforementioned sub (print_html). And it has to be the correct value! Note that the value is first set in new(). That's my problem and my question. Thanks.

----------

Update: This is not my real question. I am not deleting it as others might find it useful (and there are replies). I posted it too quickly, without thinking it through first. I hate when that happens!

This is my real question. Thank you to those who replied to this one.

Replies are listed 'Best First'.
Re: Referencing an object's value
by Tanktalus (Canon) on Jan 21, 2005 at 22:45 UTC

    What you're looking for is a way to make perl more like C++ or Java, enforcing some sort of privilege (public, private, protected, package(Java)). Perl doesn't do that. Perl takes a completely different tract.

    There is a simple convention in perl: any function with a leading underscore (which would be against The Rules(TM) in C - that is reserved for the compiler vendor) is considered "private." Other packages can call it, but it's not recommended - do so at your own risk.

    That said, there are ways to enforce things like this. For example, you could create "sessions", and store the real object data in a private hash, e.g.:

    my %data; # private hash sub new { my $data = rand(); my $self = bless \$data; $data{$$self}{BKG_IMAGE} = 'image'; } my $bkg_img = # private anon-sub sub { my $self = shift; if (@_) { $data{$$self}{BKG_IMAGE} = shift; } $data{$$self}{BKG_IMAGE}; } # called as: $self->$bkg_img('new_image') # or $image = $self->$bkg_img();

    Not recommended. Just document that _bkg_img is a private internal method. You'd be surprised how often a method you think should be private really shouldn't be ;-)

Re: Referencing an object's value
by Errto (Vicar) on Jan 21, 2005 at 23:15 UTC
Re: Referencing an object's value
by holli (Abbot) on Jan 21, 2005 at 23:04 UTC
    you
  • donīt use strict;
  • donīt use the two argument form of bless();
  • donīt get a reference to self in your method
  • use the bareword self where you mean $self in new()

  • That is what causes the wrong behavior of your class.
    Compare to this code (that works as intended):
    use strict; my $p = Foo->new(); $p->bkg_img("whatever"); $p->print_html; package Foo; sub new { my $class = shift; my $self = {}; $self->{BKG_IMAGE} = "image"; bless($self, $class); return $self; } sub bkg_img { my $self = shift; $self->{BKG_IMAGE} = $_[0]; } sub print_html { my $self = shift; print <<"HTML"; $self->{BKG_IMAGE} HTML }

    holli, regexed monk
    A reply falls below the community's threshold of quality. You may see it by logging in.