访问另一个函数中创建的对象

时间:2016-09-13 11:52:42

标签: perl

我的程序创建了一个对象,而该对象又创建了另一个对象

MainScript.pm

use module::FirstModule qw ($hFirstModule);

$hFirstModule->new(parametres);
$hFirstModule->function();

FirstModule.pm

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

2 个答案:

答案 0 :(得分:4)

取决于。

我们必须看到实际的代码。你所展示的有点含糊不清。但是,有两种情况。

  1. 您无法

    如果你的代码与伪代码的代码不完全相同,那么就没有机会这样做了。请考虑&module1::function中的此代码。

    sub function {
        my $obj = Module2->new;
        # ... more stuff
        return;
    }
    

    在这种情况下,您没有返回任何内容,$obj 词法范围lexical scope意味着它只存在于最近的{}块内(以及其中的所有块)。这是function sub的块。一旦程序返回该子程序,该变量将超出范围并且该对象将被销毁。事后没有办法达到目的。它已经消失了。

    即使它没有被销毁,也无法达到不同的范围。

  2. 您可以

    但是如果你从函数中返回对象,那么你必须在脚本中分配它,然后你可以在以后访问它。如果代码完全符合您上面显示的内容,则可以使用。

    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

  3. 这很模糊,但如果没有更多信息,就不可能更准确地回答这个问题。

答案 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问题,您需要更好地解释为什么需要这样做,以便找到一个不那么疯狂的解决方案。