|
In a message dated 3/28/2006 10:57:40 P.M. Eastern Standard Time,
[EMAIL PROTECTED] writes:
> Hey William,
> > Ok, I've dug around, and I've got a working solution to my problem. It's > a bit ugly though: > > package BaseClass; > ... > sub doThis > { > my $pFunc; > eval '$pFunc = \&'.ref($this).'::doThat'; > return threads->new($pFunc,$this); > } > > package DerivedClass; > ... > sub doThat > { > ... > } > > Essentially, the 3 lines of code does the following: > 1. ref($this) returns the class name > 2. eval is needed to get the pointer to the instance's overloaded class > subroutine, and store it in $pFunc > 3. use $pFunc directly as a parameter in new() > > My question is: is there a cleaner way to do this: ie without the use of > eval? hi ji-haw --
(btw -- i hope the above form of address is proper. if it is
not, or if you would
prefer something else, please let me know.)
i think it should be possible to avoid the use of eval() in
your code by using
``soft'' references to subroutines. see some examples below to
give you some ideas.
however, although i'm not confident i understand just what you're doing, it
seems
to me there would be an even cleaner way to handle things by
re-organizing the
structure of the object being created so that it would include a hard
reference to
the function at issue. (see amended -- and untested --
code below; look for the
####s for changes.) by doing this, the need for a method in one
class to ``know''
the name of and directly reference a method in another class is
eliminated.
remember, it was too much knowledge that got adam and eve thrown out of the
garden of eden!
hth -- bill walters
-----------------------begin code ---------------------------
#### tested code use strict;
use warnings; package Foo; sub foo { my $message = shift; print qq(i am in foo: $message \n)
}
package main; # ``direct'' invocation
Foo::foo(1); # &{Foo::foo}(2); # 'ambiguous use...' warning - not sure why no strict 'refs'; # allow use of ``soft'' subroutine references
&{'Foo::foo'}(3);
'Foo::foo'->(4); my $soft_foo = 'Foo::foo';
$soft_foo->(5); my ($function, $class) = qw(foo Foo);
# "$class::$function"->(6); # no! `::' ambiguous in double-quoted string "${class}::${function}"->(6); # canonical string interpolation __END__
#### CAUTION: UNTESTED CODE ####
use strict;
use warnings; use threads; use threads::shared; $|=1;
Worker->new(id=>1)->start; while (1)
{ sleep 1; } # ********************************************************************
# BaseThreadedWorker class # ******************************************************************** package BaseThreadedWorker; use strict; use warnings; use threads; use threads::shared; sub new ($)
{ my ($class) = @_; my %hash : shared =
(
_status=>'STOPPED', ); return bless \%hash,$class;
} sub start
{ my $this = shift; ###### return
threads->new(\&onStart,$this);
##### DELETE
# use hard function ref ``passed back'' in blessed hash # that $this references. return threads->new($this->{_start_function_ref}, $this); ##### ADD } sub status
{ my ($this,$value) = @_; lock $this;
return $this->{status} if (!defined($value)); $this->{status} = $value; } # ********************************************************************
# Worker class # ******************************************************************** package Worker; use strict; use warnings; use base 'BaseThreadedWorker'; sub new
{ my ($class,%option) = @_; my $this = $class->SUPER::new;
$this->{logger} = $option{logger} if ($option{logger}); # add hard function ref in class where the method is
defined
# and ``pass it back'' in blessed hash. $this->{_start_function_ref} = \&onStart; ##### ADD bless $this,$class;
return $this; } sub onStart
{ my $this = shift; $this->status('STARTING');
eval { while (1) { foreach my $status (qw(EATING PLAYING HIDING SLEEPING WORKING)) { { lock $this; $this->status($status); } sleep(2); if (!int(rand(5))) { die "ARGH!"; } } } }; $this->status('STOPPED'); } 1;
----------------------- end code ------------------------------
|
_______________________________________________ ActivePerl mailing list [email protected] To unsubscribe: http://listserv.ActiveState.com/mailman/mysubs
