Beefy Boxes and Bandwidth Generously Provided by pair Networks
Clear questions and runnable code
get the best and fastest answer
 
PerlMonks  

Instance field access from private methods

by markcsmith (Novice)
on Oct 23, 2002 at 18:02 UTC ( [id://207474]=perlquestion: print w/replies, xml ) Need Help??

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

Monks, This is probably a question resulting from a java-based intro to oo design. I'm still working on the conversion to perl, so please bear with me :) Let's say there's code currently executing inside of a private method in an instance of the Monkey class. I would like this code to be able to access some instance fields, but do not want to keep passing $self around from private method to private method. My (limited) understanding of perl tells this would be a job for accessing the symbol table for this instance. I could not find anything like this in the camel book (the closest thing used a non-oo example w/ the %main:: symbol table), so chances are I'm looking in the wrong places or for the wrong thing. Any help would be greatly appreciated. Mark
  • Comment on Instance field access from private methods

Replies are listed 'Best First'.
Re: Instance field access from private methods
by perrin (Chancellor) on Oct 23, 2002 at 18:18 UTC
    Plain and simple: if you don't pass $self, it is not a method. It can't be inherited, overriden, etc. You aren't supposed to pass $self explicitly; perl takes care of it for you.

    Also, stay away from the symbol table. It's a dangerous place.

      I'm not too sure. I wrote this (first time messing w/ iheritence w/ perl), and C2 obviously inherited the method printWorld even though printWorld isn't passed the invocant of printGoodBye.

      C1.pm:
      *******
      package C1; sub new { my $class = shift; my $self = {}; return bless $self, $class; } sub printGoodBye{ print "Goodbye @_ "; printWorld(); } sub printWorld{ print "World\n @_"; } 1; END {}

      C2.pm
      ******
      package C2; use base ("C1"); sub new { my $class = shift; my $self = {}; return bless $self, $class; } sub printHi{ print "Hi\n"; } 1; END {}

      o.pl
      ****
      #!/usr/bin/perl use C2; $bob = C2->new(); $bob->printGoodBye(); exit 0;


      Let me know if I'm wrong, but this sure looks like it's inheriting something w/o $self being passed to me. Mark

        Let me know if I'm wrong, but this sure looks like it's inheriting something w/o $self being passed to me.

        But it *is* passed, actually $bob is passed as the first element of @_ which is seen in the output

        Goodbye C2=HASH(0x177f054) World

        So you would normally shift off the first element to a lexical variable often called $self to use the subroutine as a method in OO-style

        sub printGoodBye { my $self = shift; print "Goodbye "; $self->printWorld(); } sub printWorld{ my $self = shift; print "World\n "; }

        So inheritance is really in play here.
        I am also a newbie when it comes to perl-OO, so I watch this thread with keen interest.(++)

      if you don't pass $self, it is not a method. It can't be inherited

      Unless you pass $class instead.

Re: Instance field access from private methods
by robartes (Priest) on Oct 23, 2002 at 18:40 UTC
    perrin is eminently right. Object Oriented Perl is based on three little rules, one of which states that methods are just subroutines which always receive a reference to the instance implementation (usually, but by no means always, a blessed hash) as their first argument. We might be misunderstanding what you are saying, but if you are passing $self (the ref to the instance) around yourself, something's wrong and you're not doing OO Perl.

    And, again as perrin says, stay out of the symbol table if you don't know what you're doing - there be dragons there. Not that I know what I'm doing or have let that little fact stop me from messing around with the symbol table myself, but be warned that I have holes in my feet as a consequence.

    A very good book (well, the book really) on Object Oriented Perl is, amazingly enough, Object Oriented Perl, by the_damian, aka Damian Conway.

    One of the pieces of advice in this book is that it is a good idea that even your private methods use the class' public accessor methods to get at private instance attributes. That way, there's no frustating hunting through your code when you change the implementation of one of your attributes.

    CU
    Robartes-

Re: Instance field access from private methods
by chromatic (Archbishop) on Oct 23, 2002 at 23:27 UTC

    No one has yet explained why the symbol table won't help you. Most objects are stored in lexical variables, which aren't held in a symbol table. It's possible to store an object in the package's symbol table, but by the time you take into account multiple concurrent objects, you've gone to more trouble than its worth to do the same thing using an object invocant gives you for almost free. :)

Re: Instance field access from private methods
by rr (Sexton) on Oct 24, 2002 at 16:25 UTC
    This is very simple. Perl will automagically pass the object as the first argument to the subroutine if you use one of the method invocation syntaxes. When you say private method, what exactly do you mean btw? There is only one way that I know of to *enforce* private methods which is to make a lexical reference in the package to the subroutine. Once within a public method, the private method is visible and callable via method invocation. Back to your question. When calling a private method from a public method, just call like:
    sub public_method { my $object = shift; $object->private_method; } sub private_method { my $object = shift; ... }
    Basically, unless you create a lexical variable that contains a CODE ref, there is no way to really create and enforce a private method that I know of. This is by design BTW. Perl wisdom says that you shouldn't need a shotgun to keep people out of your living room. Thus your private methods are just conventions based on name normally. Like sub __private_method {}; rr

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://207474]
Approved by fglock
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others romping around the Monastery: (3)
As of 2024-04-26 01:21 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found