I am working on a little Perl module and for some reason I had the test driver script that was using my new module call one of the functions that I thought would be private, and it was successful. I was surprised, so I started searching google and I couldn't really find any documentation on how to make private functions in Perl modules...
I saw one place that said to put a semicolon after the closing brace of your "private" function, like this:
sub my_private_function {
...
};
I tried that, but my driver script could still access the function I wanted to be private.
I'll make up something that will be a shorter example, but here's what I'm after:
Module TestPrivate.pm:
package TestPrivate;
require 5.004;
use strict;
use warnings;
use Carp;
use vars qw($VERSION @ISA @EXPORT @EXPORT_OK);
require Exporter;
@ISA = qw(Exporter AutoLoader);
our @EXPORT_OK = qw( public_function );
our @EXPORT = qw( );
$VERSION = '0.01';
sub new {
my ( $class, %args ) = @_;
my $self = {};
bless( $self, $class );
$self->private_function("THIS SHOULD BE PRIVATE");
$self->{public_variable} = "This is public";
return $self;
}
sub public_function {
my $self = shift;
my $new_text = shift;
$self->{public_variable} = $new_text;
print "Public Variable: $self->{public_variable}\n";
print "Internal Variable: $self->{internal_variable}\n";
}
sub private_function {
my $self = shift;
my $new_text = shift;
$self->{internal_variable} = $new_text;
}
Driver: TestPrivateDriver.pl
#!/usr/bin/perl
use strict;
use TestPrivate 'public_function';
my $foo = new TestPrivate();
$foo->public_function("Changed public variable");
$foo->private_function("I changed your private variable");
$foo->public_function("Changed public variable again");
$foo->{internal_variable} = "Yep, I changed your private variable again!";
$foo->public_function("Changed public variable the last time");
Driver output:
Public Variable: Changed public variable
Internal Variable: THIS SHOULD BE PRIVATE
Public Variable: Changed public variable again
Internal Variable: I changed your private variable
Public Variable: Changed public variable the last time
Internal Variable: Yep, I changed your private variable again!
So I added a semicolon after the last closing brace in the module, but the output is still the same. The only thing I really found was to add this line as the first line to my private_function:
caller eq __PACKAGE__ or die;
But that seems pretty hacky. I don't have a lot of experience writing Perl modules, so maybe I am setting my module up incorrectly? Is it possible to have private functions and variables in perl modules?
Thanks for helping me learn!
If you use a system like Moose, you can get a public/private distinction as seen here.
There is only "The Kludge" of storing a code reference in a lexical variable, which no one outside that scope can see:
And I can't think of a way to make rigorously "protected" fields.
That's it as far as I know ( besides source filters...shhhh. I didn't mention them.... )
EDIT: Actually, it turns out I can think of a very messy way of doing protected. But it would probably involve passing all calls through the
AUTOLOAD
sub. (!!)Just check caller:
In File for your package: Define private methods as CODE-Ref, i.e.:
We can write some thing below in the perl private function to check whehter the call from the same obj as
caller[0]
gives package.From
perldoc perltoot
(about a quarter way through the document):Therefore, I recommend you put an underscore or two at the beginning of your "private" methods to help dissuade usage.