【问题标题】:How to return the correct object attribute in perl?如何在 perl 中返回正确的对象属性?
【发布时间】:2016-09-13 01:21:06
【问题描述】:

我创建了一个包,用于返回对象的指定属性(缩短的代码)

package vendor_info;

my $vars;
sub new{
    my $class = shift;
    $vars = {
        _servers => shift,
        _locations => shift,
        _favorite => shift,
        _default_selection => shift,
        _database => shift,
        _DB => shift};

    bless $vars, $class;
    return $vars;
}
sub get_locations{
    return $vars->{_locations};
}

sub get_database{
    return $vars->{_database};
}
sub get_DB{
    return $vars->{_DB};
}

我的 perl 文件接收从终端解析的输入,但在这种情况下,变量 $vendor 是硬编码用于测试的。我有一个散列中的对象列表,我想根据对象返回正确的属性。一些变量已用占位符删除。

$vendor = "atrena";

my %vendor_hash = (
    "atrena" => new vendor_info("Variable_server","Variable_location","Advanced_CDC|CDC dftso|DFT|gui|GUI|adv_checker|Lint|spl-view-only|view-only-GUI","adv_checker","database","DB"),

    "ansys" => new vendor_info("Variable","Location","agppi|agppi|ane3fl|ane3fl|ansys|ansys|ensemble_gui|ensemble_gui|hfss_desktop|hfss_desktop|hfss_gui|hfss_gui|hfss_solve|hfss_solve|hfsshpc_pack|hfsshpc_pack|optimetrics|optimetrics|q3d_desktop|q3d_desktop|rdacis|rdacis|struct|struct","ane3fl","database", "db"),

    "coventor" => new vendor_info("var","location","COV_ZsplatViewer|Viewer|COV_VoxelModeler|Voxel-Modeler|MEMSp_Import_Package|Import-Package|MEMSp_Innovator_Plugin|Innovator-Plugin|MEMSp_MATLAB_Simulation|MATLAB-Simulation|MEMSp_Platform|Platform|MTI_AutoBuilder|Auto-Builder|MTI_Catapult|Catapult|MTI_CoventorWare|Coventor-Ware|MTI_Memcap|Memcap|MTI_PreProcessor|PreProcessor","database","db","db")   

);

$vendor_object = $vendor_hash{$vendor};

print Dumper( $vendor_object);

$foodb = $vendor_object -> get_database();

转储程序正在打印正确的信息,但是,当我调用 get_database() 时,调用的数据库始终是列表中最后一个对象的属性,在本例中是 coventor。对于任何子例程 getter 都可以这样说。

如何为正确的对象调用正确的属性?

【问题讨论】:

    标签: perl object hash


    【解决方案1】:

    你有$vars 作为一个词法变量,它的作用域是包含你的包的文件。所以这个变量只有一个实例,它总是包含最后一个设置的对象的数据。

    我不确定您是从哪里采用这种方法的,但这根本不是 Perl 对象的工作方式。 $vars 的作用域应该只存在于您的构造函数中,并且您的访问器应该使用传递给它们的对象作为它们的第一个参数(传统上称为 $self)。

    # Only pragmas should start with lower-case letters
    package VendorInfo;
    
    sub new{
        my $class = shift;
        my $vars = {
            _servers => shift,
            _locations => shift,
            _favorite => shift,
            _default_selection => shift,
            _database => shift,
            _DB => shift
        };
    
        return bless $vars, $class;
    }
    
    # Just one example accessor...
    sub get_database{
        my $self = shift;
        return $self->{_database};
    }
    

    还有一点,请使用Class->new() 而不是您在代码中使用的可能有问题的new Class 语法。

    【讨论】:

      【解决方案2】:

      Dave Cross 已经 answered 您的直接问题。

      这是您的代码的更惯用版本的示例:

      {
          package VendorInfo;
          use Moo;
      
          for my $attr (qw(
              servers
              locations
              favorite
              default_selection
              database
              DB
          )) {
              has $attr => (
                  is       => 'ro',
                  required => 1,
              );
          }
      }
      
      
      # main program
      use strict;
      use warnings;
      
      use Data::Dumper;
      
      my %vendor_hash = (
          "atrena" => VendorInfo->new(
              servers           => "Variable_server",
              locations         => "Variable_location",
              favorite          => "Advanced_CDC|CDC dftso|DFT|gui|GUI|adv_checker|Lint|spl-view-only|view-only-GUI",
              default_selection => "adv_checker",
              database          => "database",
              DB                => "DB",
          ),
      
          "ansys" => VendorInfo->new(
              servers           => "Variable",
              locations         => "Location",
              favorite          => "agppi|agppi|ane3fl|ane3fl|ansys|ansys|ensemble_gui|ensemble_gui|hfss_desktop|hfss_desktop|hfss_gui|hfss_gui|hfss_solve|hfss_solve|hfsshpc_pack|hfsshpc_pack|optimetrics|optimetrics|q3d_desktop|q3d_desktop|rdacis|rdacis|struct|struct",
              default_selection => "ane3fl",
              database          => "database",
              DB                => "db",
          ),
      
          "coventor" => VendorInfo->new(
              servers           => "var",
              locations         => "location",
              favorite          => "COV_ZsplatViewer|Viewer|COV_VoxelModeler|Voxel-Modeler|MEMSp_Import_Package|Import-Package|MEMSp_Innovator_Plugin|Innovator-Plugin|MEMSp_MATLAB_Simulation|MATLAB-Simulation|MEMSp_Platform|Platform|MTI_AutoBuilder|Auto-Builder|MTI_Catapult|Catapult|MTI_CoventorWare|Coventor-Ware|MTI_Memcap|Memcap|MTI_PreProcessor|PreProcessor",
              default_selection => "database",
              database          => "db",
              DB                => "db",
          ),
      );
      
      my $vendor = "atrena";
      
      my $vendor_object = $vendor_hash{$vendor};
      
      print Dumper($vendor_object);
      
      print "The database is: ", $vendor_object->database, "\n";
      

      注意事项:

      • 我将vendor_info 重命名为VendorInfo。小写的模块名称(非正式地)保留给 pragmata。
      • 我使用Moo 作为编写类的辅助模块。
      • Moo 提供了一个has 辅助函数来声明属性。它还为我生成了一个构造函数,因此我不必自己编写任何样板。
      • Moo 会自动启用warnings/strict,所以我也不必这样做。
      • 间接对象语法(method $objectmethod class,在您的情况下为new vendor_info)是一个坏主意,因为它的语法歧义。 class->method(这里:VendorInfo->new)要好得多。
      • 由 Moo 创建的构造函数以键值对的形式获取其参数,而不是一个长列表(如果您的 sub 使用超过 3 个参数,这无论如何都是个好主意)。
      • 我声明的每个属性都有一个(只读(因为我使用了'ro'))访问器,因此客户端代码可以简单地使用$object->database

      【讨论】:

      • 我喜欢你展示的这个,而且解释很好而且很有用。但我认为for ... has 对于一个真正不熟悉这个的人来说有点太没有样板了。它错过了演示 has 的工作原理,我认为可能会非常混乱。
      • 好吧,你也可以写has 'servers' => (is => 'ro', required => 1); has 'locations' => (is => 'ro', required => 1); has 'favorite' => (is => 'ro', required => 1); ...,但我无法忍受所有的复制/粘贴。 :-(
      【解决方案3】:

      除了其他人的观点,你还需要在你的.pm文件末尾添加一个true声明

      这就是我将如何编写您的应用程序

      供应商信息.pm

      package VendorInfo;
      
      use strict;
      use warnings 'all';
      
      sub new {
          my $class = shift;
      
          my $self;
      
          @{$self}{qw/
              _servers
              _locations
              _favorite
              _default_selection
              _database _DB
          /} = @_;
      
          return bless $self, $class;
      }
      
      sub get_locations {
          my $self = shift;
          return $self->{_locations};
      }
      
      sub get_database {
          my $self = shift;
          return $self->{_database};
      }
      
      sub get_DB {
          my $self = shift;
          return $self->{_DB};
      }
      
      1;
      

      main.pl

      use strict;
      use warnings 'all';
      
      use VendorInfo;
      use Data::Dumper;
      
      my $vendor = 'atrena';
      
      my %vendor_hash = (
          atrena => VendorInfo->new(
              'Variable_server',
              'Variable_location',
              'Advanced_CDC|CDC dftso|DFT|gui|GUI|adv_checker|Lint|spl-view-only|view-only-GUI',
              'adv_checker',
              'database',
              'DB',
          ),
          ansys => VendorInfo->new(
              'Variable',
              'Location',
              'agppi|agppi|ane3fl|ane3fl|ansys|ansys|ensemble_gui|ensemble_gui|hfss_desktop|hfss_desktop|hfss_gui|hfss_gui|hfss_solve|hfss_solve|hfsshpc_pack|hfsshpc_pack|optimetrics|optimetrics|q3d_desktop|q3d_desktop|rdacis|rdacis|struct|struct',
              'ane3fl',
              'database',
              'db',
          ),
          coventor => VendorInfo->new(
              'var',
              'location',
              'COV_ZsplatViewer|Viewer|COV_VoxelModeler|Voxel-Modeler|MEMSp_Import_Package|Import-Package|MEMSp_Innovator_Plugin|Innovator-Plugin|MEMSp_MATLAB_Simulation|MATLAB-Simulation|MEMSp_Platform|Platform|MTI_AutoBuilder|Auto-Builder|MTI_Catapult|Catapult|MTI_CoventorWare|Coventor-Ware|MTI_Memcap|Memcap|MTI_PreProcessor|PreProcessor',
              'database',
              'db',
              'db',
          ),
      );
      
      my $vendor_object = $vendor_hash{$vendor};
      
      print Dumper $vendor_object;
      
      my $foodb = $vendor_object->get_database;
      
      print $foodb, "\n";
      

      输出

      $VAR1 = bless( {
                       '_servers' => 'Variable_server',
                       '_default_selection' => 'adv_checker',
                       '_locations' => 'Variable_location',
                       '_database' => 'database',
                       '_DB' => 'DB',
                       '_favorite' => 'Advanced_CDC|CDC dftso|DFT|gui|GUI|adv_checker|Lint|spl-view-only|view-only-GUI'
                     }, 'VendorInfo' );
      database
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2014-11-29
        • 1970-01-01
        • 2016-07-05
        • 1970-01-01
        • 2018-05-18
        • 1970-01-01
        • 2022-11-03
        相关资源
        最近更新 更多