When I was at YAPC::2006, a talk of chromatic's got me to thinking about a better way of producing inside-out objects. My idea proved troublesome, but here's the interface I wanted:
use Encapsulation;
sub new {
bless {}, shift;
}
sub foo {
my $self = shift;
return $self->{foo} unless @_;
$self->{foo} = shift;
}
1;
In other words, I wanted inside-out objects to act like a normal blessed hash. You know, if inside-out objects were that simple, more people would use them. I've stopped using them because they're so painful to me. I was talking about this idea to adrianh and he suggested a different approach than my foolish attempt to use a tied and blessed hash. Then he sent me the code.
#!/usr/bin/perl
use strict;
use warnings;
{ package Encapsulate;
use Scalar::Util;
BEGIN {
my $Secrets = {};
use overload
'%{}' => sub {
my $id = Scalar::Util::refaddr( shift );
my $package = caller;
return $Secrets->{ $id }->{ $package } ||= {};
},
fallback => 1;
sub DESTROY {
my $id = Scalar::Util::refaddr( shift );
delete $Secrets->{ $id };
};
}
}
{ package Foo;
use base qw( Encapsulate );
sub new {
my $class = shift;
return bless {}, $class;
}
sub foo {
my $self = shift;
$self->{ secret } = shift if @_;
return $self->{ secret };
}
}
{ package Bar;
use base qw( Foo );
sub bar {
my $self = shift;
$self->{ secret } = shift if @_;
return $self->{ secret };
}
}
use Test::More tests => 6;
isa_ok my $o = Bar->new, 'Bar';
$o->foo( 42 );
is $o->foo, 42, "can set and get value of Foo's secret";
Bar->new->foo( 24 );
is $o->foo, 42, "different objects get different secrets";
$o->bar( 99 );
is $o->bar, 99, "can set and get value of Bar's secret";
is $o->foo, 42, "secrets of different classes do not interfere";
ok !defined $o->{secret}, 'cannot reach into objects';
It's not complete (no serialization support, for one thing), but wow, that's pretty easy! So go ahead, shoot holes in this approach.
-
Are you posting in the right place? Check out Where do I post X? to know for sure.
-
Posts may use any of the Perl Monks Approved HTML tags. Currently these include the following:
<code> <a> <b> <big>
<blockquote> <br /> <dd>
<dl> <dt> <em> <font>
<h1> <h2> <h3> <h4>
<h5> <h6> <hr /> <i>
<li> <nbsp> <ol> <p>
<small> <strike> <strong>
<sub> <sup> <table>
<td> <th> <tr> <tt>
<u> <ul>
-
Snippets of code should be wrapped in
<code> tags not
<pre> tags. In fact, <pre>
tags should generally be avoided. If they must
be used, extreme care should be
taken to ensure that their contents do not
have long lines (<70 chars), in order to prevent
horizontal scrolling (and possible janitor
intervention).
-
Want more info? How to link
or How to display code and escape characters
are good places to start.