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

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.


Worth throwing at CPAN?

In reply to Private method variations by adrianh

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?

    What's my password?
    Create A New User
    and all is quiet...

    How do I use this? | Other CB clients
    Other Users?
    Others examining the Monastery: (4)
    As of 2018-02-26 04:33 GMT
    Find Nodes?
      Voting Booth?
      When it is dark outside I am happiest to see ...

      Results (316 votes). Check out past polls.