Beefy Boxes and Bandwidth Generously Provided by pair Networks
more useful options
 
PerlMonks  

Re^3: Writing Modules/namespace polution

by Mugatu (Monk)
on Mar 16, 2005 at 17:00 UTC ( #440021=note: print w/replies, xml ) Need Help??


in reply to Re^2: Writing Modules/namespace polution
in thread Writing Modules/namespace polution

they are essentially protected by virtue of the fact that you have to use the object

I would be careful about calling much in Perl protected. Sure, general politeness will keep most people from using the package in unintended ways, but Perl sure won't:

Module

package Example::Module; use strict; sub new { bless {}, shift } sub foo { my ($s, $v1, $v2) = @_; print "Hi '$v1' and '$v2'\n"; } 1;

Script

use strict; use Example::Module; # add a new sub to the package sub Example::Module::bar { my ($s, $v1, $v2) = @_; print "Bye '$v1' and '$v2'\n"; } my $em = Example::Module->new; $em->bar("one", "two"); # call the sub not as a method Example::Module::foo('one', 'two', 'three'); # change the existing sub *Example::Module::foo = sub { my ($s, $v1, $v2) = @_; print "Oops '$v1' and '$v2'\n"; }; $em->foo("one", "two");

Replies are listed 'Best First'.
Re^4: Writing Modules/namespace polution
by thekestrel (Friar) on Mar 16, 2005 at 18:01 UTC
    Thanks Mugatu,

    I see what you mean, protection is a relative term when you have ahold of the object. Is there a way of privatizing variables/member functions of a package as you would with a C/C++ class so you can limit the interface size, otherwise without reading about each function via documention for the package its not clear from quickly scanning the code which functions are meant to be part of the interface?


    Regards Paul.
      Is there a way of privatizing variables/member functions of a package

      The only way I know of is through lexical variables. You can use them to create closures that only the enclosed blocks have access to. There are ways to get around this protection, but they're not pretty or for the faint of heart. Here's the basic example:

      package Example::Module; use strict; { # this variable is not accessible outside of the block # that it's in. thus, any access to it must go through # the subroutines defined in this block. my $variable; sub accumulate { $variable += $_ for @_ } sub printvalue { print $variable, $/ } } 1;

      You could use that package like so:

      use Example::Module; Example::Module::accumulate(5,6,7); Example::Module::printvalue;

      Using anonymous coderefs, you can get the same protection for subroutines:

      package Example::Module; use strict; { my $value; # this lexical variable stores a subroutine that is only # accessible from within this block. my $add = sub { $value += $_[0] }; sub accumulate { $add->($_) for @_ } sub printvalue { print $value, $/ } } 1;

      Now, a problem comes in when you want to use these techniques with objects. Converted to an object interface, these lexical variables would be persistent across all instances of the object. Trying to use them for instance data would obviously be a problem. Thus, you have to keep track of the instances yourself.

      One way to do this is to make each data member a hash that is keyed on the object instance's reference ID. You have to be careful to remove these instance variables when the object is destroyed, though, because the hash is persistent throughout the program's lifetime. Note, this is an approach that Abigail-II developed, called inside-out objects. Here's a very minimal example:

      package Example::Module; use strict; # note, we don't actually have to use the reference that we # bless. we just need it for its unique reference id. sub new { bless {}, shift } { my %value; my %counter; sub accumulate { my $self = shift; for (@_) { $value{ $self } += $_; $counter{ $self }++; } } sub printvalue { my $self = shift; printf "%s has value %2d from %2d iterations.\n", $self, $value{$self}, $counter{$self}; } # prevent memory leaks. DESTROY { my $self = shift; delete $value{$self}; delete $counter{$self}; } } 1;

      Of course, it's neat that you can get this protection if you really need it. But most of the time, my experience shows that you don't really need it. Most of the community simply relies on politeness and common conventions, such as using _ in the beginning of private method names.

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: note [id://440021]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others lurking in the Monastery: (7)
As of 2019-12-15 09:49 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found

    Notices?