首页 > 解决方案 > Perl:如何使用现有包作为新类/对象的基础

问题描述

我有一个 Perl 包,它不是作为 OOP 类编写的。我们称之为 PkgA。PkgA 定义了子程序和变量。

我想在我的主包中实例化它两次,每个实例都有自己的包变量值集。

我认为将 PkgA 变成一个类,并通过构造该类的 2 个对象来实例化它两次将是正确的路径。

为了演示我的问题,我创建了两个文件:PkgA.pm 和 Mail.pl - 它们出现在底部。

PkgA 包含对象变量和局部变量的混合。

对象变量:_CoreName_is_uchipsim_testOOPVar。它们代表了我在将 PkgA 转换为对象时添加的那些变量。

局部变量:NonOOPVar。它代表原始的 PkgA 变量。

程序在 Main 下创建两个 PkgA 实例:main_PkgA 和 aux_PkgA。然后它为 main_PkgA 调用 process_args,然后是 aux_PkgA。

OOPVarprocess_args 为和 赋值NonOOPVar。在 main_PkgA 中,它们将为 {100,101},在 aux_PkgA 中,它们将为 {200,201}。

然后程序在两个实例中调用 load_mem。此子例程仅打印 OOPVar 和 NonOOPVar。您可以在打印到屏幕的输出中看到:

main_PkgA: NonOOPVar = 200, OOPVar = 101
aux_PkgA  : NonOOPVar = 200, OOPVar = 201   

因此,OOPVar 都具有正确的值,但 main_PkgA 的 NonOOPVar 带有 aux_PkgA 的值!

我需要找到一种方法让 NonOOPVar 知道它所属的实例。


PkgA.pm

#!/usr/bin/perl

package PkgA;
require 5.000;

push(@ISA,PkgA.pm);
 
sub new {
    print ("Package PkgA::new was called \n");
    my $class = shift;
    # Receive parameters from the containing module
    my $self = {
        _CoreName         => shift,
        _is_uchipsim_test => shift,
        OOPVar            => None
    };
    printf("Class = %s, Core name = %s is_uchipsim_test = %d, OOPVar = %d\n",$class,$self->{_CoreName},$self->{_is_uchipsim_test},$self->{OOPVar});
    bless $self, $class;
    return $self;
};

sub get_core_name {
    my ($self) = shift;
    return $self->{_CoreName};
}
sub get_is_uchipsim_test {
    my ($self) = shift;
    return $self->{_is_uchipsim_test};
}

my ($NonOOPVar);
sub process_args {  
    $this = shift @_;
    my (@args) = @_;
    $NonOOPVar = @args[0];
    $this->{OOPVar} = $NonOOPVar + 1;
    printf("this = %s, args size = %d, args[0] = %s, NonOOPVar = %d, OOPVar = %d\n",$this, scalar @args, $args[0],$NonOOPVar,$this->{OOPVar});
};

sub load_mem {
    $this = shift @_;
    printf("load_mem, this = %s, NonOOPVar = %d, OOPVar = %d  \n",$this, $NonOOPVar,$this->{OOPVar});
};

1;

主文件

#!/usr/bin/perl

use PkgA;

$main_PkgA       = new PkgA("PkgA_main",1); # Arguments of new(): _CoreName, _is_uchipsim_test,
$aux_PkgA        = new PkgA("PkgA_aux" ,2);
$MainCoreName    = $main_PkgA->get_core_name();
$AuxCoreName     = $aux_PkgA->get_core_name();
printf("Main: Instantiate systest_dot11acphy for MAIN core. Printing its CoreName field: %s\n",$main_PkgA->get_core_name());
printf("Main: Instantiate systest_dot11acphy for AUX  core. Printing its CoreName field: %s\n",$aux_PkgA->get_core_name());

$main_PkgA->process_args(100);
$aux_PkgA->process_args(200);

$main_PkgA->load_mem();
$aux_PkgA->load_mem();

标签: perloop

解决方案


这有几件事不对劲。首先,使用 strict 和 warnings 将帮助您解决几乎所有的错误。

use strict;
use warnings;

使用它来创建新对象。您的另一种方式是间接对象表示法。这不好

$aux_PkgA        = PkgA->new("PkgA_aux" ,2);

使用 $ 获取单个值,使用 @ 获取多个值

sub process_args {  
my $this = shift @_;
my (@args) = @_;
$this->{NonOOPVar} = $args[0];
$this->{OOPVar} = $this->{NonOOPVar} + 1;
printf("this = %s, args size = %d, args[0] = %s, NonOOPVar = %d, OOPVar = %d\n",$this, scalar @args, $args[0],$this->{NonOOPVar},$this->{OOPVar});
};

你正在调用一个你不想调用的值。您启动了一个不是对象本地的变量 $NonOOPVar。它在对象之间共享,因为它在主程序范围内。使用 strict 和 warning 可以清楚地说明这是如何发生的,而您将无法做到这一点。

 printf("load_mem, this = %s, NonOOPVar = %d, OOPVar = %d  \n",$this, $this->{NonOOPVar},$this->{OOPVar});

PkgA.pm

#!/usr/bin/perl
use strict;
use warnings;
package PkgA;
my $NonOOPVar = 200;
sub new {
    print ("Package PkgA::new was called \n");
    my $class = shift;
    # Receive parameters from the containing module
    my $self = {
        _CoreName         => shift,
        _is_uchipsim_test => shift,
        OOPVar            => undef
    };
    printf("Class = %s, Core name = %s is_uchipsim_test = %d, OOPVar = %d\n",$class,$self->{_CoreName},$self->{_is_uchipsim_test},$self->{OOPVar});
    bless $self, $class;
    return $self;
};

sub get_core_name {
    my ($self) = shift;
    return $self->{_CoreName};
}
sub get_is_uchipsim_test {
    my ($self) = shift;
    return $self->{_is_uchipsim_test};
}

sub process_args {  
    my $this = shift @_;
    my (@args) = @_;
    $this->{NonOOPVar} = $args[0];
    $this->{OOPVar} = $this->{NonOOPVar} + 1;
    printf("this = %s, args size = %d, args[0] = %s, NonOOPVar = %d, OOPVar = %d\n",$this, scalar @args, $args[0],$this->{NonOOPVar},$this->{OOPVar});
};

sub load_mem {
    my $this = shift @_;
    printf("load_mem, this = %s, NonOOPVar = %d, OOPVar = %d  \n",$this, $this->{NonOOPVar},$this->{OOPVar});
    #printf("load_mem, this = %s, NonOOPVar = %d, OOPVar = %d  \n",$this, $NonOOPVar,$this->{OOPVar});

};

1;

主文件

#!/usr/bin/perl

use strict;
use warnings;
use PkgA;

my $main_PkgA       = PkgA->new("PkgA_main",1); # Arguments of new(): _CoreName, _is_uchipsim_test,
my $aux_PkgA        = PkgA->new("PkgA_aux" ,2);
my $MainCoreName    = $main_PkgA->get_core_name();
my $AuxCoreName     = $aux_PkgA->get_core_name();
printf("Main: Instantiate systest_dot11acphy for MAIN core. Printing its CoreName field: %s\n",$main_PkgA->get_core_name());
printf("Main: Instantiate systest_dot11acphy for AUX  core. Printing its CoreName field: %s\n",$aux_PkgA->get_core_name());

$main_PkgA->process_args(100);
$aux_PkgA->process_args(200);

$main_PkgA->load_mem();
$aux_PkgA->load_mem();

推荐阅读