Re: Accessors
Rocco Caputo <[email protected]>
| Newsgroups | gmane.comp.lang.perl.poe |
|---|---|
| Message-ID | <[email protected]> |
My favorite method (har) is to wrap the session in an object that acts
as its interface and also its storage.
POE::Component::Client::KeepAlive is implemented this way.
In brief, new() creates the object and spawns a hidden POE::Session.
object_states map events to private methods on the new object. Public
methods on the object act as accessors and mutators, and can be used
to send commands into the hidden session.
sub new {
my $class = shift;
my $self = bless { }, $class;
POE::Session->create(
object_states => {
_start => "_poe_start_handler",
lala_changed => "_poe_lala_changed",
do_something => "_poe_do_something",
...,
}
);
return $self;
}
The session's _start handler sets its alias to be the stringified
object reference. More on this later.
sub _poe_start_handler {
$_[KERNEL]->alias_set("$_[OBJECT]");
}
From event handlers:
sub _poe_handler {
my ($self, $heap) = @_[OBJECT, HEAP];
$self->{lala} = 123; # visible from $object->accessor()
$heap->{lala} = "abc"; # not visible from the OO interface
}
From accessors:
sub accessor {
my $self = shift;
return $self->{lala};
}
Mutators can trigger POE events by calling "$self" (stringified object
reference). This is the alias set in _poe_start_handler().
sub mutator {
my ($self, $new_lala) = @_;
$self->{lala} = $new_lala;
$poe_kernel->call("$self", lala_changed => $new_lala);
return $new_lala;
}
sub _poe_lala_changed {
my $new_lala = $_[ARG0];
my $other_new_lala = $_[OBJECT]{lala};
# do something here
}
And "command" methods can call "$self" without setting members.
sub do_something {
my $self = shift;
$poe_kernel->call("$self", do_something => @_);
}
sub _poe_do_something {
# don't just stand there!
return "result";
}
...
This isn't a best practice, however. It implies a 1:1 ration of
sessions to objects, which isn't ideal. The ideal, best way is to
implement a dispatcher that lets many objects share a smaller set of
sessions. POE::Stage is implemented this way, but it's not ready for
production yet.
A compromise: Embed POE sessions in I/O objects, and use regular Perl
objects for everything else.
--
Rocco Caputo - [email protected]
On Apr 8, 2008, at 20:04, John R. wrote:
> From the 1.0 documentation (very good by the way):
>
> "call() returns the value returned by the EVENT_NAME handler. It
> can do
> this because the handler is invoked before call() returns. call() can
> therefore be used as an accessor, although there are better ways to
> accomplish simple accessor behavior."
>
> (from POE::Kernel)
>
> I don't see reference to the better ways so they probably are
> standard perlish ways of doing things that I am having difficulty
> figuring out. What other ways are there to accomplish accessors that
> provide access to POE things like the heap? I am doing calls within
> a session and between sessions. Should I pass the heap, kernel, etc
> as arguments to regular sub calls?
>
> Thanks,
>
> John