Hi guys,

I was just reading about closures on perl.com and read that Tom Christiansen said that closures can be used to achieve data hiding in OO perl. I thought about it and came up with an example to do that:

A module written without closures:

package Dinner; use strict; use warnings; my $self = {}; sub new { my ($class) = @_; bless $self, $class; return $self; } sub washhands { my ($obj) = @_; $obj->{'handsclean'} = 1; return 1; } sub eatfood { my ($obj) = @_; if (exists $obj->{'handsclean'}) { print "\nYou washed your hands -eat all you want\n"; } else { print "\nYou filthy animal!! Go wash your hands\n"; } return 1; } 1;

Its corresponding use:

#!/usr/bin/perl -w use strict; use Dinner; my $dirtyeater = Dinner->new(); # I don't want to wash hands, I will just set the flag directly # $dirtyeater->washhands; $dirtyeater->{'handsclean'} = 1; $dirtyeater->eatfood;

A Data::Dumper dump of $dirtyeater gives

$VAR1 = bless( { 'handsclean' => 1 }, 'Dinner' );

$dirtyeater can eat food if he knows what to change in the objects data structure. I know that if you are playing with the object's ds you do it at your own risk but I want to prevent the end user from changing any object ds specific variables. So I write another module called Dinnerclosure.pm:

package Dinnerclosure; use strict; use warnings; sub new { my ($class) = @_; my $self = {}; my $selfmirage = {}; $selfmirage->{'washhands'} = sub { washhands($self); }; $selfmirage->{'eatfood'} = sub { eatfood($self); }; bless $selfmirage, $class; return $selfmirage; } sub washhands { my ($obj) = @_; $obj->{'handsclean'} = 1; return 1; } sub eatfood { my ($obj) = @_; if (exists $obj->{'handsclean'}) { print "\nYou washed your hands -eat all you want\n"; } else { print "\nYou filthy animal!! Go wash your hands\n"; } return 1; } 1;

The testcode:

#!/usr/bin/perl -w use strict; use Dinnerclosure; my $cleaneater = Dinnerclosure->new(); # comment next line and uncomment the one after it, but it won't wash +hands $cleaneater->{'washhands'}->(); #$cleaneater->{'handsclean'} = 1; $cleaneater->{'eatfood'}->(); print Dumper $cleaneater;

$dirtyeater cannot change the 'cleanhands' flag. If he does, he will be changing the $selfmirage hashref which does not decide cleanliness, $self does. And $dirtyeater cannot access $self because the object is:

$VAR1 = bless( { 'eatfood' => sub { "DUMMY" }, 'washhands' => sub { "DUMMY" } }, 'Dinnerclosure' );

Advantages:

  1. You have to wash hands before eating. :) - to generalize - you can only call subs to manipulate data.There is no other choice.
  2. $self and $selfmirage are lexically scoped within the new sub. They don't even have to be declared at top of package before any subs in case of Dinner.pm - better lexical scoping
  3. The end user does not see any object innards in the ds

WYDSIWYDG - What you don't see is what you don't get :)

-- Saurabh


In reply to Using closures to achieve data hiding in OO Perl by saurabh.hirani

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.