Reputation: 221
What is the correct way to handle methods which will not be called by the user? For example if the user calls a method, say do_stuff()
from a driver script, and if do_stuff()
relies on other subroutines, is it best practice to call those subs from within the do_stuff()
method as follows:
sub do_stuff {
my ( $self, %arg ) = @_;
#does it things
#and then calls the private sub as follows
_private_sub( $self, %arg );
}
Upvotes: 4
Views: 524
Reputation: 66944
If your do_stuff
method needs the functionality that you decided should be kept "private" then by all means call _private_sub
within it. That is precisely its purpose. Of course, having a method be "private" is a matter of convention as it cannot be enforced.
I'd like to mention another way, of using coderefs for private subs
my $_private = sub { ... }; # must be at least predeclared
sub do_stuff {
my ($self, %arg) = @_;
# ...
my $from_private = $self->$_private(@args); # or
my $more_private = $_private->($self, @args);
}
The syntax is of the first call is odd but then that also warns that it is meant as a private facility. Note that this is a trick of sorts -- while $self
is indeed passed as the first argument, one could use any old reference instead of $self
and the call works and $_private
is passed that.
Using this makes it harder for subclasses to inherit, thanks to mob for emphasizing this.
The second invocation uses $_private
as a function rather than like a method, so we have to pass the object if it needs it. This further warns against its use. It clearly doesn't undergo any method lookup process (and is thus slightly faster), something to be well aware of.
I am a little uncertain as to what exactly the question seeks.
If it is about whether to use "private" subroutines in your code, then there is really no accepted best practice. They can be very useful, of course. But they are either not truly private or, if you hide them as lexicals that cannot be seen from outside the unit (scope) like here, their behavior differs so much that that itself is an issue. I use them, with due care.
A better approach is probably to use Moose or Moo, or some other module. The organizational conveniences may shift the focus so that issues of "privacy" never come up. Also, a variety of tools and features that come in the ecosystem surrounding them may make it easier to handle special needs. But these libraries do not provide any special magic that would provide "true" private methods ("private" like in some other languages), thanks to simbabque for emphasizing this.
Introduced in v5.18, and stable since 5.26, we have lexical subroutines. They are defined with my sub ...
(or state
) and exist only within their lexical scope. So surely nothing outside the file can see them. Go read up and play.
However, I find that one cannot use them via the method call syntax. I don't know about the design decisions and am not sure why that is, but one cannot do
# NOPE -- Can't locate object method "lexisubname" via package...
$self->lexisubname(...)
unlike for a lexical coderef, which can be called via ->
and the caller (a reference) is passed to it, as misleading as that may be. Unless I am missing something, that would restrict the use of lexical subs to a function call, where $self
has to be passed in explicitly if needed.
Related:
There's got to be more similar pages discussing this.
Upvotes: 4
Reputation: 69314
All of the answers you have received so far say that it can't be done. But it can - in Perl 5.18 and later. See the section on lexical subroutines in perldoc perlsub
.
Lexical Subroutines
WARNING: Lexical subroutines are still experimental. The feature may be modified or removed in future versions of Perl.
Lexical subroutines are only available under the
use feature 'lexical_subs'
pragma, which produces a warning unless the "experimental::lexical_subs" warnings category is disabled.Beginning with Perl 5.18, you can declare a private subroutine with
my
orstate
. As with state variables, the state keyword is only available underuse feature 'state'
oruse 5.010
or higher.These subroutines are only visible within the block in which they are declared, and only after that declaration:
no warnings "experimental::lexical_subs"; use feature 'lexical_subs'; foo(); # calls the package/global subroutine state sub foo { foo(); # also calls the package subroutine } foo(); # calls "state" sub my $ref = \&foo; # take a reference to "state" sub my sub bar { ... } bar(); # calls "my" sub
To use a lexical subroutine from inside the subroutine itself, you must predeclare it. The
sub foo {...}
subroutine definition syntax respects any previousmy sub;
orstate sub;
declaration.my sub baz; # predeclaration sub baz { # define the "my" sub baz(); # recursive call }
Upvotes: 2
Reputation: 2444
To my knowledge, there's no "correct" way. Perl doesn't provide the ability to hide the functions, at least that I've ever run across. What I've done is use a naming standard where I start the internal-only function names with an underscore and clearly document that they're never to be called by external callers.
EDIT: The other answers triggered a thought. In each private method, you could check the results of the "caller ()" function and abort if the caller is anyone other than the local module. Honestly, I personally wouldn't go to the trouble, but if it's really important to you for some reason, that would emphasize the private nature of these methods.
Upvotes: 4
Reputation: 118665
As opposed to $self->_private_sub(...)
? In my mind, the $obj->_method
notation is always used with function that act on an instance of your class, and other kinds of calls are always used for other kinds of functions.
But if you're going to be paranoid, why not use an unconventional way of packing your arguments that will confound anyone that tries to use your private method in an object oriented way?
sub do_stuff {
my ( $self, %arg ) = @_;
...
_private_sub( %arg, $self );
}
sub _private_sub {
my $self = pop;
my %args = @_;
...
}
Upvotes: 0