Perl:使用Class :: Struct vs显式Perl对象引用

时间:2015-05-14 16:11:52

标签: perl

我对Perl很新,所以请耐心等待......我最近看到一个使用Class::Struct的脚本:

Class::Struct

#!/usr/bin/perl

package Animal;

use strict;
use warnings;

use Class::Struct;

struct Animal => {
  species => '$'
};

sub species {
  print "In species";
}

package main;

my $x;
$x = Animal->new;

输出:物种

我的理解是,这基本上是以下的捷径:

Perl object reference

#!/usr/bin/perl

package Animal;

use strict;
use warnings;

sub new {
  my $class = shift;
  my $self = {};
  bless $self, $class;
  return $self;
}

sub species {
  print "In species";
}

package main;

my $x;
$x = Animal->new;

输出:

我没想到Class::Struct示例输出:物种。这似乎表明结构中列出的所有子/方法都在运行Animal->new时运行,但我不确定为什么会出现这种情况。我希望Class::Struct只创建访问器方法,并为我提供一个new方法来获取对象引用。

所以我的问题是:

  • 我的理解基本上是正确的吗?
  • 为什么Class::Struct在初始化时运行所有方法?
  • 我错过了什么吗?

更新 在Perl 5.18.0之前,这不是默认行为,如下所示:https://rt.perl.org/Public/Bug/Display.html?id=29230

2 个答案:

答案 0 :(得分:4)

如果您有一个名为species的属性,Class:Struct会为此设置名为species的访问者,并且它还会调用该访问者以在对象期间使用undef对其进行初始化构造:

  

struct数据中的每个元素都有一个访问器方法,用于分配元素并获取其值。可以通过在包中声明具有相同名称的sub来覆盖默认访问器。 (见例2)

     

...

     

标量('$''*$'

     

元素是标量,默认情况下初始化为undef

您通过定义名为species不是访问者的子项来混淆该过程。您永远无法设置species字段的值,并且每次尝试阅读species的值时,您都会获得1和#34} ;在物种"正在印刷,这只会使事情混乱。

事实上,运行你的例子已经告诉你发生了什么:

  

function 'species' already defined, overrides struct accessor method at ./struct.pl line 10.

#!/usr/bin/perl

package Animal;

use strict;
use warnings;

use Class::Struct;

struct Animal => {
  species => '$'
};

package main;

my $x;
$x = Animal->new;

$x->species('specious');

print $x->species, "\n";

所以,回答你的问题:

  
      
  • 为什么Class::Struct在初始化时运行所有方法?
  •   

它没有运行所有方法。它正在使用访问器初始化对象,因为良好的封装需要。

答案 1 :(得分:4)

取自Class::Struct's documentation

  

struct数据中的每个元素都有一个访问器方法,用于分配元素并获取其值。可以通过在包中声明具有相同名称的sub来覆盖默认访问器。 (见例2)

后来(重点补充):

  

标量('$'或'* $')

     

元素是标量,默认情况下初始化为undef (但请参阅“使用new初始化”)。

     

将访问者的参数(如果有)分配给元素。

new调用尝试通过调用程序包中定义的访问者子speciesspecies属性设置为undef。

作为访问者例程中的Dumper调用显示:

sub species {
  print "In species\n";
  use Data::Dumper;
  print Dumper(\@_);
}

输出:

In species
$VAR1 = [
      bless( {}, 'Animal' ),
      undef
    ];