我的程序创建了一个对象,而该对象又创建了另一个对象
use module::FirstModule qw ($hFirstModule);
$hFirstModule->new(parametres);
$hFirstModule->function();
use Exporter ();
@EXPORT = qw($hFirstModule);
use module::SecondModule qw ($hSecondModule);
sub new {
my $className = shift;
my $self = { key => 'val' };
bless $self, $classname;
return $self;
}
sub function{
$hSecondModule->new(parametres);
#some other code here
}
我想从$hSecondModule
访问MainScript.pm
。
答案 0 :(得分:4)
取决于。
我们必须看到实际的代码。你所展示的有点含糊不清。但是,有两种情况。
您无法
如果你的代码与伪代码的代码不完全相同,那么就没有机会这样做了。请考虑&module1::function
中的此代码。
sub function {
my $obj = Module2->new;
# ... more stuff
return;
}
在这种情况下,您没有返回任何内容,$obj
词法范围。 lexical scope意味着它只存在于最近的{}
块内(以及其中的所有块)。这是function
sub的块。一旦程序返回该子程序,该变量将超出范围并且该对象将被销毁。事后没有办法达到目的。它已经消失了。
即使它没有被销毁,也无法达到不同的范围。
您可以
但是如果你从函数中返回对象,那么你必须在脚本中分配它,然后你可以在以后访问它。如果代码完全符合您上面显示的内容,则可以使用。
sub function {
my $obj = Module2->new;
# nothing here
}
在Perl中,subs总是返回最后一个true语句。如果您没有return
并且最后一个语句是Module2->new
调用,则返回该语句的结果,即该对象的结果。当然,如果您明确地return
,它也会起作用。
sub function {
return Module2->new;
}
因此,如果将其分配给脚本中的变量,则可以在脚本中访问它。
my $obj = module1->function();
这类似于the factory pattern。
这很模糊,但如果没有更多信息,就不可能更准确地回答这个问题。
答案 1 :(得分:3)
这是一种非常hacky的方法,可以考虑更新的代码。它使用Sub::Override来获取对SecondModule东西的构造函数调用的返回值。这通常可以在单元测试中进行,但不能在生产代码中进行。但是,它应该工作。这是一个例子。
Foo.pm
package Foo;
use Bar;
sub new {
return bless {}, $_[0];
}
sub frobnicate {
Bar->new;
return;
}
Bar.pm
package Bar;
sub new {
return bless {}, $_[0];
}
sub drink {
return 42; # because.
}
script.pl
package main;
use Foo; # this will load Bar at compile time
use Sub::Override;
my $foo = Foo->new;
my $bar; # this is lexical to the main script, so we can use it inside
my $orig = \&Bar::new; # grab the original function
my $sub = Sub::Override->new(
"Bar::new" => sub {
my $self = shift;
# call the constructor of $hSecondModule, grab the RV and assign
# it to our var from the main script
$bar = $self->$orig(@_);
return $bar;
}
);
$foo->frobnicate;
# restore the original sub
$sub->restore;
# $bar is now assigend
print $bar->drink;
同样,我不会在生产代码中这样做。
让我们来看看main
功能。它首先创建一个新的Foo对象。然后它抓取对Bar::new
函数的引用。我们需要它作为原始,所以我们可以调用它来创建对象。然后我们使用Sub :: Override将Bar::new
临时替换为调用原始的sub,但是获取返回值(即对象)并将其分配给我们的变量,该变量是主要的词汇。脚本。然后我们回来了。
现在,$foo->frobnicate
调用Bar->new
时会调用此函数。在该调用之后,在我们的主脚本中填充$bar
。然后我们会恢复Bar::new
,这样我们就不会意外覆盖$bar
,以防再次从其他地方再次调用。
之后,我们可以使用$bar
。
请注意,这是先进的。我再说一遍,我不会在生产代码中使用这种黑客攻击。可能有更好的方法来做你想要的。这里可能存在x / y问题,您需要更好地解释为什么需要这样做,以便找到一个不那么疯狂的解决方案。