【问题标题】:why does perl constructor not initialize the package(class) variables [closed]为什么perl构造函数不初始化包(类)变量[关闭]
【发布时间】:2016-03-05 17:11:07
【问题描述】:

当调用 perl 构造函数时,类引用被传递给新函数,但构造函数不会像 java 或 c++ 那样初始化类变量。相反,它会创建一个新的 Hash 并在类引用中祝福它并返回它。这会创建子程序不能直接引用变量的问题,他们必须使用传递的隐式引用。

以下代码将突出显示该问题:-

package foo;
use strict;
my $var1;
my $var2;
my $var3;

sub new {
    my $class = shift;
    my $self  = {
        var1 => shift,
        var2 => shift,
        var3 => shift
      };

    bless $self, $class;
    return $self;

      }

sub method {

        my $self = shift;
        print(
            "variable value are $self->{var1},$self->{var2},$self->{var3}";
       #how to directly refer to var1 declared above? instead of self->{var1} 
       }

很明显,封装方法必须使用引用 self 才能使用 var1,var2,var3 这不是包变量,而只是散列的对象。

1:-这意味着在perl中没有办法初始化包变量?? 2:-如果我用某种方法显式地初始化它们,它们是对所有对象都有一个副本还是每个对象都有不同的副本

【问题讨论】:

  • 在 Perl 中就是这样。包作用域变量类似于 Java 中的类变量。 - Perl 发行版中有几个 OO 教程。为初学者阅读这些内容。
  • 示例代码已损坏。它有不平衡的大括号,并且有 new 方法调用 new 方法。如果代码更清晰,可能会更容易理解这个问题。
  • 是的,更正了!!!谢谢

标签: perl class-variables


【解决方案1】:

使用包变量的规范方法是使用our 声明它们。在包之外,您可以通过使用包限定变量名来引用它们。

package foo;
our ($var1, $var2, $var3) = (5, 42, "bar");
sub new { bless { var4 => $_[1] }, $_[0] }
...
1;


package main;
use foo;
$obj = foo->new(19);   # instance of foo
print "Instance variable is $obj->{var4}\n";    # 19
print "Package variable is $foo::var1\n";       #  5

【讨论】:

  • 谢谢,在方法之外我们可以改变包变量的值吗??
【解决方案2】:

在 Perl 中,包变量,例如:文件顶部的my $var1,不是实例变量。它们对应于 Java 或 C# 等语言中的静态变量。在 Perl 中,通常使用 $self,而其他语言使用 this。某些语言,如 Java,允许您在引用成员变量时省略 this 的使用。有些,比如 JavaScript 和 Perl 没有。

如果您询问如何初始化静态变量,您当然可以通过在创建它们时分配给它们来做到这一点。

package foo;
use strict;
use warnings;
my $created_at = localtime();

sub created_at {
  return $created_at;
}

sub new {
  my($pkg,$p1,$p2) = @_;
  my $self = {
    prop1 => $p1,
    prop2 => $p2
  };
  return bless $self, $pkg;
}

# you can create accessors, think of these as getters and setters, if you pass a value it is set
sub prop1 { my($self,$v) = @_; $self->{prop1} = $v if @_>1; return $self->{prop1}; } 
sub prop2 { my($self,$v) = @_; $self->{prop2} = $v if @_>1; return $self->{prop2}; }

sub method {
  my($self) = @_;
  print "prop1=",$self->{prop1},"; prop2=",$self->{prop2},"\n";
}

package main;
use strict;
use warnings;

print "created_at = ",foo->created_at,"\n";

my $f = foo->new("banana","apple");

print "f->created_at = ", $f->created_at,"\n";
$f->method();
$f->prop1('orange');
$f->method();

这是一种在 Perl 中处理 OO 的旧方法,基于 Perl5 对对象的初始支持。如果您更熟悉其他对象系统,您可能想看看 Perl 的 Moose 库,它提供了您可能习惯的更多内容。

HTH,

凯尔

【讨论】:

  • 感谢您的解释。静态一词几乎消除了所有疑问。在调用包时,可以在这些静态字段上使用 setter 来动态设置值。我们如何在 perl 中创建实例变量??
  • 嗨@RahulKumar 在我的例子中,prop1prop2 是实例变量。你熟悉 Javascript 吗?对象在 JS 和 Perl 中具有非常相似的语义。 $self->{prop1}一个成员变量。您可以通过分配 $self->{prop99} 随时“创建”新的(再次就像在 JS 中一样)
  • 嗨@kyle,我知道 prop1 和 prop2 是您创建的哈希的键,它们被祝福到引用中,它们可以被认为是实例变量。要再次访问这些我必须使用 $self这是在函数中传递的。我想问的是有没有一种方法可以将包变量声明为实例变量?或者包变量总是静态的???
  • 是的,$selfsub 之外的任何内容都是包变量。
猜你喜欢
  • 2018-01-10
  • 2016-01-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-09-27
  • 2015-02-19
相关资源
最近更新 更多