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

Perl 访问在另一个函数中创建的对象,perl,Perl,我的程序创建了一个对象,而这个对象又创建了另一个对象 MainScript.pm 下午1:00 我想从MainScript.pm访问$hSecondModule,这取决于具体情况。 我们必须看到实际的代码。你所展示的有点模棱两可。然而,有两种情况 你不能 如果您的代码与您显示的伪代码不完全相同,那么就没有机会这样做。在代码>和模块1::函数 中考虑此代码。 sub function { my $obj = Module2->new; # ... more stuff

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

MainScript.pm 下午1:00
我想从
MainScript.pm
访问
$hSecondModule
,这取决于具体情况。

我们必须看到实际的代码。你所展示的有点模棱两可。然而,有两种情况

  • 你不能

    如果您的代码与您显示的伪代码不完全相同,那么就没有机会这样做。在代码>和模块1::函数

    中考虑此代码。
    sub function {
        my $obj = Module2->new;
        # ... more stuff
        return;
    }
    
    在本例中,您没有返回任何内容,
    $obj
    是词汇范围。A表示它只存在于最近的
    {}
    块(以及该块内的所有块)内部。这是
    函数
    sub的块。一旦程序返回该sub,变量将超出范围,对象将被销毁。之后就没办法去了。它不见了

    即使它没有被破坏,你也不能进入一个不同的范围

  • 你可以

    但是,如果从函数返回对象,则必须在脚本中分配它,然后才能稍后访问它。如果代码与上面显示的代码完全相同,那么这是可行的

    sub function {
        my $obj = Module2->new;
        # nothing here
    }
    
    在Perl中,sub总是返回最后一条true语句。如果没有
    return
    ,并且最后一条语句是
    Module2->new
    调用,则返回该语句的结果,即对象。当然,如果您确实显式地
    返回
    ,它也会起作用

    sub function {
        return Module2->new;
    }
    
    因此,如果将其分配给脚本中的变量,则可以在脚本中访问它

    my $obj = module1->function();
    
    这类似于


  • 这是含糊不清的,但是如果没有更多的信息,就不可能更准确地回答这个问题。

    这里有一个非常粗糙的方法,它考虑了您的更新代码。它用于获取对第二个模块的构造函数调用的返回值。这是您通常可能在单元测试中执行的操作,但不是在生产代码中。然而,它应该起作用。这里有一个例子

    下午五时

    下午三点

    script.pl

    同样,我不会在生产代码中这样做

    让我们看看
    main
    函数。它首先创建一个新的Foo对象。然后它获取对
    Bar::new
    函数的引用。我们需要它作为原始的,所以我们可以调用它来创建对象。然后,我们使用Sub::Override临时用Sub替换
    Bar::new
    ,Sub调用原始的,但获取返回值(即对象)并将其分配给主脚本的词法变量。然后我们把它退回

    现在,当
    $foo->frobnite
    调用
    Bar->new
    时,将调用此函数。在该调用之后,
    $bar
    将填充到主脚本中。然后我们恢复
    Bar::new
    ,这样我们就不会意外地覆盖
    $Bar
    ,以防从其他地方再次调用它

    之后,我们可以使用
    $bar


    请注意,这是高级的。我要再说一遍,我不会在生产代码中使用这种黑客行为。也许有更好的方法来做你想做的事。这里可能存在x/y问题,您需要更好地解释为什么需要这样做,以便我们可以找到一个不那么疯狂的解决方案。

    基于条件返回对象并分配给变量?请显示您正在使用的实际代码,或至少一个变量。没有这些,就不可能最终回答你的问题。如果你回答了这个问题,并且包括了你实际上在做什么,我会更新我的答案来反映这一点。我在函数中更新了我的代码,第二个对象没有返回,这是否意味着它在词汇范围内,我无法以任何方式访问它?我不能修改第一个模块,这就是为什么我要这么做,听到这个消息我很难过。但是,如果你知道这很奇怪而且不是通常的做事方式,那么这是一次很好的经历。使用这样的代码可以学到很多东西。我认为这是无价的。你学会了关注细节,意识到自己在做什么,处理额外的奇怪事情。当然,你学会了如何不做事,将来你将能够非常有效地论证为什么这样做是个坏主意感谢您的解释,显然我正在尝试访问一个范围外的变量,这是不可能的,因为它丢失了,因为当它离开
    {}
    范围时,它持有一个空引用。如果您将模块文件和主文件分开,这不会有什么坏处,而且我认为会更清楚source@borodin对我以后再做。我的目标是便于复制。我总是讨厌在尝试编写代码时必须创建几个文件。我同意这样做可以使你的代码更容易测试,但是要把你写的东西转换成单独的模块文件,特别是对于那些比较幼稚的读者来说,难度要大得多。我认为那些想要将代码压缩到单个源文件中的人可能比那些需要将单个块扩展到单个源文件中的人更容易受到阻碍,也更不频繁。它也可能绕过人们认为“正确”的方法是使用多个库文件,除非您明确地这样说。谢谢你的回答。@Borodin我刚改了。我完全同意你的意见。我明白了!谢谢你在这里所做的一切。
    sub function {
        return Module2->new;
    }
    
    my $obj = module1->function();
    
    package Foo;
    use Bar;
    
    sub new {
        return bless {}, $_[0];
    }
    
    sub frobnicate {
        Bar->new;
        return;
    }
    
    package Bar;
    
    sub new {
        return bless {}, $_[0];
    }
    
    sub drink {
        return 42;    # because.
    }
    
    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;