Reputation: 1656
I am trying to build a small application with base module 'Apps' and shared instance module "Shared" among all modules like "View" and "Request" so all data and methods in "Shared" module will be available for all other modules which extends it (View, Request, Apps) same instance, below is the code example.
app.cgi
#!/usr/bin/perl
use Moose;
use Apps;
my $app = Apps->new;
msg(); # exported, works ok
$app->msg(); # as method works ok
my $view = $app->view;
$view->msg; # view class method, works ok
print $app->charset . "\n"; # from Shared.pm, prints utf8, default
$app->charset("windows-1256"); # change from utf8 to windows-1256 in Shared.pm
print $app->charset . "\n"; # this now ok, prints windows-1256
print $view->charset . "\n"; # this is not ok, the same default utf8
exit;
Apps.pm
package Apps;
use Moose;
extends qw(Shared);
sub init {
print "true is: " . true()."\n";
}
1;
View.pm
package View;
use Moose;
extends qw(Shared);
sub msg {
print "Hello msg from View\n";
}
1;
Request.pm
package Request;
use Moose;
extends qw(Shared);
sub msg {
print "Hello msg from request\n";
}
1;
when I run app.cgi I get this output:
Hello msg from Shared
Hello msg from Shared
Hello msg from View
utf8
windows-1256
utf8
what I am expecting is:
Hello msg from Shared
Hello msg from Shared
Hello msg from View
utf8
windows-1256
windows-1256
so the changes to the Shared module is not reflected or shared with View and other modules. How to make one instance of the object Shared shared among all extending classes.
My goal is to make all packages extend on Shared package and that package should share the same instance data among all extensions.
Upvotes: 1
Views: 66
Reputation: 13664
Shared
shouldn't be a base class that all your objects inherit from. The Shared
class should be a completely separate from an inheritance point of view.
Instead, each class should have an attribute (this might be a private one called something obscure beginning with an underscore), that point to a shared object from the Shared
class. When one object creates another object (in your example, the $app object creates a $view object) it can assign the new object a pointer to its instance of the Shared
class.
Something like this:
use v5.14;
package Shared {
use Moose;
has foo => (is => 'rw', default => 99);
has bar => (is => 'rw', default => 42);
}
package App {
use Moose;
has _common => (
is => 'ro',
default => sub { Shared->new },
handles => [qw/ foo bar /],
);
sub view {
my $self = shift;
View->new(@_, _common => $self->_common);
}
}
package View {
use Moose;
has _common => (
is => 'ro',
required => 1,
handles => [qw/ foo bar /],
);
}
my $app = App->new;
my $view = $app->view;
say '$app->foo : ', $app->foo;
say '$view->foo : ', $view->foo;
# change the value of $app->foo.
# this will be shared with $view.
$app->foo(66);
say '$app->foo : ', $app->foo;
say '$view->foo : ', $view->foo;
Upvotes: 1