Perl继承相同的实例

时间:2014-04-24 04:16:57

标签: perl

我正在尝试使用基本模块“Apps”构建一个小型应用程序,并在“View”和“Request”等所有模块中共享实例模块“Shared”,以便“共享”模块中的所有数据和方法都可供所有人使用扩展它的其他模块(View,Request,Apps)相同的实例,下面是代码示例。

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;

当我运行app.cgi时,我得到了这个输出:

Hello msg from Shared
Hello msg from Shared
Hello msg from View
utf8
windows-1256
utf8

我期待的是:

Hello msg from Shared
Hello msg from Shared
Hello msg from View
utf8
windows-1256
windows-1256

因此,不会反映或与View和其他模块共享对共享模块的更改。 如何使对象的一个​​实例在所有扩展类之间共享。

我的目标是使所有包在Shared包上扩展,并且该包应该在所有扩展中共享相同的实例数据。

1 个答案:

答案 0 :(得分:1)

Shared不应该是所有对象都从中继承的基类。 Shared类应该与继承的观点完全分开。

相反,每个类都应该有一个属性(这可能是一个私有的属性,称为以下划线开头的隐藏),指向Shared类的共享对象。当一个对象创建另一个对象时(在您的示例中,$ app对象创建一个$ view对象),它可以为新对象分配一个指向其Shared类实例的指针。

这样的事情:

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;