http://www.perlmonks.org?node_id=332916


in reply to Private method variations

If you want to avoid namespace clashes, you can just avoid the method lookup entirely and pass the object as the first parameter to the private method (this happens anyway, we just aren't faking it). As a bonus, the subroutine lookup time is reduced:

my $private1 = sub { print "Private1\n" }; sub _private2 { print "Private2\n" } sub public_method { my $self = shift; $private1->($self); _private2($self); }

Calling like this shouldn't be done for public and protected methods because it breaks subclassing, but private methods aren't supposed to be subclassed anyway.

----
: () { :|:& };:

Note: All code is untested, unless otherwise stated

Replies are listed 'Best First'.
Re^2: Private method variations
by adrianh (Chancellor) on Mar 01, 2004 at 14:40 UTC
    If you want to avoid namespace clashes, you can just avoid the method lookup entirely and pass the object as the first parameter to the private method

    This option was mentioned several times in the OP you know :-)

    Two problems:

    • Using a different calling style makes it harder to switch to/from private/public methods since we have to change the way $self is passed
    • The method name is still in the main namespace, so subclasses can call it accidentally leading to potentially odd results
      Nevertheless, it's the use of the same calling style that is the root of the problem.

      Perl 6 will have a compromise solution to this. The calling style for a private method is very like, but not quite the same as, the calling style for a public method. All private attributes and method names will start with a distinguishing character, which at the moment I would guess is colon, though at one time it was exclamation mark. Anyway,

      has $.foo; # public attribute has $:bar; # private attribute method foo (){...} # public method method :bar () {...} # private method ... $self.foo() # always calls public method virtually .foo() # unary variant $self.:bar() # always calls private method .:bar() # unary variant ... $self.bar() # calls public bar, not private.
      In this way, you don't have to change your argument passing--it's just a matter of inserting an extra character. The calls are also self-documenting, since you can tell by inspection whether you're looking for something public or private. Likewise, any use of $.foo is obviously public, while any use of $:foo is obviously private.
        Perl 6 will have a compromise solution to this. The calling style for a private method is very like, but not quite the same as, the calling style for a public method. All private attributes and method names will start with a distinguishing character, which at the moment I would guess is colon, though at one time it was exclamation mark.

        Is this in addition to the submethods mentioned in Apocalypse 6, which seem to solve the same sort of issues?

        The self documenting aspect is nice - one of the things I like about Ruby.

        (I am so looking forward to A12 :-)

        $self.bar() # calls public bar, not private.

        This seems to imply that you can have both public and private methods/attributes with (almost) the same name. Sounds like trouble to me.