Re: overload proxy object
- From: anno4000@xxxxxxxxxxxxxxxxxxxxxxx (Anno Siegel)
- Date: 30 Sep 2005 09:33:09 GMT
Eric Anderson <eric@xxxxxxxx> wrote in comp.lang.perl.misc:
> I have occasional objects that are heavy to instantiate. Because of the
> way the application is structured, often these objects won't even be
> used (they are available if needed but they may not be needed). So to
> reduce the resources of this application I have surrounded these objects
> with a proxy object that delays instantiation.
>
> Basically when the object is created you create it like this:
>
> my $curusr = new Class::Delayed(sub {new Data::User($uid)})
>
> Data::User is heavy because it does some database queries to get it's
> attributes. But often the code doesn't even use $curusr meaning those
> queries were for nothing. Now the proxy object looks like this:
>
> ******* BEGIN CLASS **********
>
> package Class::Delayed;
>
> sub new {
> my ( $class, $closure ) = @_;
> my $self = {};
> bless( $self, $class );
> $self->{closure} = $closure;
> return $self;
> }
>
> sub AUTOLOAD {
> my ( $self, @args ) = @_;
> $AUTOLOAD =~ s/.*:://;
> return if !exists($self->{obj}) and $AUTOLOAD eq 'DESTROY';
> $self->{obj} = $self->{closure}->() unless exists $self->{obj};
> $self->{obj}->$AUTOLOAD(@args);
> }
>
> 1;
>
> *********** END CLASS **********
>
> As you can see anytime any method is called on the object it will
> instantiate the object if it was not already created. It creates the
> object by calling the closure that was passed into the proxy object.
>
> This all works real well except when the real object is using overloads.
> Many of the objects have "", cmp and <=> overloads (for sorting and
> printing) and these no longer work. I am guessing because my overload
> methods do not pass through AUTOLOAD.
>
> I think I might be able to use the "nomethod" overload but it looks like
> my implementation of nomethod will need to look at the symbol and then
> carry out the operation according to each symbol. This seemed like a bit
> of work (not too much but a bit) so I think maybe there is a better more
> simpler way to just say "all overloads for object X get passed to object
> Y". Any ideas?
I tend to avoid AUTOLOAD if possible. It doesn't play nice with
->can and, as you have noticed, overloading can have difficulties
too.
You can use overload itself (plus inheritance) to manage the transition
from the light class to the heavy one. The light class only preserves
the arguments to ->new inside a hash object, so it can later create the
heavy object if needed. It also overloads hash access so that the
transition is triggered the first time a method tries to access the
underlying hash. A method that doesn't access the hash leaves the
object unchanged.
Here is a sketch. It doesn't follow your setup exactly (I had no
access to your posting when I wrote it), but I believe the principle
is applicable. It could probably be streamlined some more. In
particular, the class Data::User is hard-coded into Class::Delayed,
which could mess up further inheritance. See what you can do with it.
#!/usr/bin/perl
use strict; use warnings; $| = 1; # @^~`
my $obj = Class::Delayed->new( 'Otto');
print ref $obj, "\n";
$obj->no_access;
print ref $obj, "\n";
print "object stringified: $obj\n";
print ref $obj, "\n";
exit;
########################################################
package Data::User;
sub new {
my ( $class, $href, @args) = @_;
print "Hard work here\n";
$href->{ name} = shift @args;
bless $href, $class;
}
# a method that doesn't access the object proper
sub no_access {
my $obj = shift;
print "doing things without access\n";
}
# ...and a method that does access
sub name { $_[ 0]->{ name} }
use overload '""' => 'name';
########################################################
package Class::Delayed;
use base 'Data::User';
sub new {
my ( $class, @args) = @_;
bless {
args => \ @args,
}, $class;
}
sub switch {
my $obj = shift;
bless $obj, 'Data::User'; # must re-bless before access
my $args = delete $obj->{ args};
Data::User->new( $obj, @$args);
}
use overload '%{}' => 'switch';
__END__
Anno
--
If you want to post a followup via groups.google.com, don't use
the broken "Reply" link at the bottom of the article. Click on
"show options" at the top of the article, then click on the
"Reply" at the bottom of the article headers.
.
- References:
- overload proxy object
- From: Eric Anderson
- overload proxy object
- Prev by Date: Re: Perl time and Mysql time
- Next by Date: Re: Full_screen by default after loan the CGI file, anyone know
- Previous by thread: overload proxy object
- Next by thread: Call for Speakers
- Index(es):
Relevant Pages
|