Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl-Sensitive Sunglasses
 
PerlMonks  

comment on

( #3333=superdoc: print w/replies, xml ) Need Help??
There is more than an answer to this question.

  • One way is to use a lexical reference to a method:

    pl@nereida:~/LEyapp/examples$ cat localwithlocal3.pl #!/usr/local/bin/perl -w use strict; { package Tutu; my $_tutu = sub { my $self = shift; "Inside tutu. My class is ".ref($self)."\n" }; sub plim { my $self = shift; print "plim can access _tutu as a private method:\n" .$self->$_tutu; } sub new { bless {}, $_[0]; } } package main; my $obj = Tutu->new(); $obj->plim();
    Now the $_tutu method is visible only inside the closure enclosing the Tutu package.
  • Most of the time the sort of privacy we need is to avoid a descendant class accidentally overwriting a private method. In such case, calling the method as a subroutine Class::_private_method($self) instead of using the $self->_private_method syntax will suffice.
  • You can have a sort of dynamic visibility of methods beteween classes in the same hierarchy (but only one level of inheritance) using the strategy of naming a lexical CODE reference inside the client methods
    #!/usr/local/bin/perl -w use strict; package Tutu; my $protected = sub { my $self = shift; "inside Tutu::tutu!\n" }; sub plim { my $self = shift; local *protected = $protected; print "Accessing 'protected' as a method: " .$self->protected(); } sub new { bless {}, $_[0]; } package SubTutu; our @ISA = qw{Tutu}; # SubTutu can overwrite 'protected' sub protected { my $self = shift; "inside overwritten tutu!\n" }; package main; my $obj = SubTutu->new(); $obj->plim(); print(Tutu->can('protected')? (Tutu::protected()."\n") : "main does not even know of 'Tutu::protected'\n" ); $obj->plim(); # Let us provoke an exception Tutu::protected();
    When executed gives the following output:
    $ attributeprotectedwithlocal.pl Accessing 'protected' as a method: inside overwritten tutu! main does not even know of 'Tutu::protected' Accessing 'protected' as a method: inside overwritten tutu! Undefined subroutine &Tutu::protected called at ./attributeprotectedwi +thlocal.pl line 49.

  • A problem with Attribute::Protected is that the universal method "can" still see the methods qualified as private.
    When you run the following code:
    pl@nereida:~/LEyapp/examples$ cat attributeprotected.pl #!/usr/local/bin/perl -w package SomeClass; use Attribute::Protected; sub foo : Public { } sub _bar : Private { } sub _baz : Protected { } sub another { my $self = shift; $self->foo; # OK $self->_bar; # OK $self->_baz; # OK } sub new { bless {}, $_[0] } package DerivedClass; @DerivedClass::ISA = qw(SomeClass); sub yetanother { my $self = shift; $self->foo; # OK $self->_bar; # NG: private method $self->_baz; # OK } package main; my $some = SomeClass->new; $some->foo; # OK print ($some->can('_bar')?"Yes, main can see that SomeClass has a _bar + method\n":"no\n");
    produces the following output:
    $ attributeprotected.pl Yes, main can see that SomeClass has a _bar method
    But certainly the purpose of Attribute::Protected is to warn you as soon as possible of the crash rather than hide the method
  • Unfortunately -at the time of this writing - Sub::Lexical seems to be broken with modern versions of Perl. See the test results at CPAN
  • Let me tell you a story:

    I wrote Parse::Eyapp a LALR compiler compiler (s.t. similar to Parse::RecDescent). From a grammar specification produces an abstract syntax tree. The tree can then be manipulated using an attribute grammar like the one provided by Luke Palmer Language::AttributeGrammar.
    Language::AttributeGrammar was written with Parse::RecDescent in mind and assumes that node children are accesed by name instead than by ordinal number, which is the way used by Parse::Eyapp.
    Language::AttributeGrammar access to children is through a private method called _get_child.
    The fact that the private method wasn't really hidden allowed me to overwrite the method and to restore it after the modification so that if later in the program an attributed grammar - let us say for a Parse::RecDescent generated tree - needs the old version of _get_child it will work. See the pertinent fragment of code for a small calculator:

    94 my $attgram = new Language::AttributeGrammar <<'EOG'; 95 96 # Compute the expression 97 NUM: $/.val = { $/->{attr} } 98 TIMES: $/.val = { $<0>.val * $<1>.val } 99 PLUS: $/.val = { $<0>.val + $<1>.val } 100 MINUS: $/.val = { $<0>.val - $<1>.val } 101 UMINUS: $/.val = { -$<0>.val } 102 ASSIGN: $/.val = { $::s{$<0>->{attr}} = $<1>.val; $<1>.val } 103 EOG 104 105 { 106 # rewrite _get_child, save old version 107 no warnings 'redefine'; 108 *Language::AttributeGrammar::Parser::_get_child = sub { 109 my ($self, $child) = @_; 110 111 $self->child($child); 112 }; 113 114 my $res = $attgram->apply($t, 'val'); 115 } 116 # Restored old version of Language::AttributeGrammar::Parser::_ge +t_child
    Paraphrasing Larry Wall's quote, This is like going into the living room, changing a bit the things while none is using them, and cleaning and restoring them after use so that the next visitors will find them where they expect. If the living room were totally locked (I.e. if Luke Palmer decided to use a solution like the lexical closure reference above for _get_child) we couldn't do it.
    As someone else said, Perl's motto "Don't enter my private spaces unless invited to do so" carries an invisible caveat: "or you really need to".

In reply to Re: REALLY Private Methods in perl: Is Perl Flexible enough to be made Inflexible? by casiano
in thread REALLY Private Methods in perl: Is Perl Flexible enough to be made Inflexible? by penguin

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post; it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.
  • Log In?
    Username:
    Password:

    What's my password?
    Create A New User
    Chatterbox?
    and the web crawler heard nothing...

    How do I use this? | Other CB clients
    Other Users?
    Others examining the Monastery: (3)
    As of 2020-04-10 07:07 GMT
    Sections?
    Information?
    Find Nodes?
    Leftovers?
      Voting Booth?
      The most amusing oxymoron is:
















      Results (49 votes). Check out past polls.

      Notices?