daliaessam
daliaessam

Reputation: 1656

Perl inheritance same instance

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

Answers (1)

tobyink
tobyink

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

Related Questions