Beefy Boxes and Bandwidth Generously Provided by pair Networks
No such thing as a small change
 
PerlMonks  

Comment on

( #3333=superdoc: print w/ replies, xml ) Need Help??

While tidying up some code recently I was pondering the problems with the use of the _method_name() convention to indicate private methods in Perl.

Of course their are many alternative conventions that prevent the accidental overriding of methods in subclasses, for example:

package Foo; my $_private = sub { ... }; my _private = sub { ... }; sub foo { my $self = shift; # we can specify the full package name $self->Foo::_private(); # we can call as a subroutine _private($self); # we can use lexically scoped subs $self->$_private(); };

They also all have disadvantages of one sort or another, for example:

  • LongPackageNamesCanGetSomewhatTediousToType
  • Using subroutine calling style makes it harder to switch to/from private/public methods during development
  • With PackageNames and subroutine calls the method is still visible in subclasses
  • When you use lexically scoped subroutines you have to be share your method name space with your other lexical scalars

With the package name and subroutine calling methods we can prevent the method from being inherited by subclasses by putting it in a seperate package (see (tye)Re: Private Class Methods for an example). So we can do things like:

package Foo; sub Foo::private::method { ... }; sub foo { my $self = shift; $self->Foo::private::method { ... }; };

Which is nice, but we still have to repeat the Foo::private package every time we call the method - which for VeryLongPackageNames could be tedious.

A convenient shortcut to the private method space would be nice. Maybe something like:

sub Foo::MY::method { ... }; sub foo { my $self = shift; $self->MY::method(); };

This fits in quite nicely with SUPER:: and NEXT::.

This is actually pretty trivial to implement - just stick an AUTOLOAD in the MY package:

package MY; sub AUTOLOAD { my $self = shift; our $AUTOLOAD; my $method = caller() . "::$AUTOLOAD"; $self->$method(@_); };

and Bob's the parental sibling of your choice.

Unfortunately this adds an extra method call worth of overhead to every private method. Probably a bad move - Perl's method invocation is slow enough as it is.

It would also be nice to be able to do:

sub MY::method { ... };

rather than

sub MyLongPackageName::MY::method { ... };

Having to repeat MyLongPackageName for every private method definition is a pain.

Looks like a job for (and I don't say this very often because they're evil :-) a source filter.

package MY; use strict; use warnings; my $Imported_from; sub import { $Imported_from = caller }; use Filter::Simple; FILTER_ONLY code => sub { s/(\w+::)*MY::/${Imported_from}::MY::/gs }; 1;

Which will allow us to write code like this:

package Foo; use MY; sub new { bless {}, shift }; sub hello { my $self = shift; $self->MY::greet_world("hi"); }; sub MY::greet_world { my ($self, $greeting) = @_; print "$greeting world\n"; }; package Bar; use base qw(Foo); use MY; sub new { my $class = shift; $class->MY::greet_world(); return $class->SUPER::new(@_); }; sub MY::greet_world { print "A new Bar has entered the world\n"; };

Without the two private greet_world() methods of Foo and Bar interfering, and without any run-time overhead.

Neat.

Worth throwing at CPAN?


In reply to Private method variations by adrianh

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!
  • 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
  • Outside of code tags, you may need to use entities for some characters:
            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 browsing the Monastery: (16)
    As of 2014-12-18 12:32 GMT
    Sections?
    Information?
    Find Nodes?
    Leftovers?
      Voting Booth?

      Is guessing a good strategy for surviving in the IT business?





      Results (51 votes), past polls