home | O'Reilly's CD bookshelfs | FreeBSD | Linux | Cisco | Cisco Exam  


6.4 Privacy

Symbols in Perl are freely accessible; privacy is not enforced. The online documentation says, rather colorfully, "Perl does not enforce private and public parts of its modules as you may have been used to in other languages like C++, Ada, or Modula-17. Perl doesn't have an infatuation with enforced privacy. It would prefer that you stayed out of its living room because you weren't invited, not because it has a shotgun."[ 2 ]

[2] I once saw this gem in a piece of C++ code: " #define private public ", just before including a header file. Someone who wants data that badly will find a means to get at it!

In addition to accessing a foreign package's existing variables or subroutines, a package can easily create new names in another package's namespace, as we saw earlier. Consider

package Test;
# Create a variable subroutine and subroutine in another package
$main::foo = 10;    
sub 
main::myFunc
 {  
    print "Hello \n";
}

package main;
myFunc();   #  prints "Hello"

Although this is not a very kosher thing to do in a normal application, this facility can be put to good use if applied in a controlled manner. You can use it to import foreign package symbol names into your own namespace; we will study this in the next section.

6.4.1 Enforcing Privacy

You can use the my operator at file scope to get unassailably private variables. Because they are not associated in any way with a package, they cannot be accessed from a different scope (in this case, file scope). But because they don't have anything to do with packages, they are restricted at most to file boundaries. Consider

package A;
my $a = 10;   # A lexical variable

package B; 
print $A::a;  # No such variable in package A
print $a;     # prints 10, because it can see the lexical variable
              # (even though package B is in effect)

What if you want to make a subroutine name private? You cannot use my to declare a private subroutine, but you can use anonymous subroutines and hold references to them in lexical variables:

my $rs_func = sub {
                    ....
              };

Now, $rs_func can be dereferenced from within that scope (if it is a global variable anywhere within that file), but it cannot be accessed in another file. Whenever you want to call this function, you can either say &$rs_func or, if you intend to call it a number of times, use typeglob aliasing for convenience and efficiency:

{
    local (*func) = $rs_func;
    for (1..100) {func()};
}

While you can hide your own global identifiers, there's nothing you can do to prevent another module from installing new names into your namespace. In fact, older Perl libraries took this liberty a lot more. (Look at the bigint.pl package in the standard Perl library, for example.)