【问题标题】:Perl objects - class variable initializationPerl 对象 - 类变量初始化
【发布时间】:2013-05-15 08:53:03
【问题描述】:

我刚刚开始设计一个 Perl 类,而我在 OOP 方面的唯一经验是很久以前的 C++。

有几项数据我需要成为“类变量”——由所有实例共享。我希望它们在我第一次实例化一个对象之前被初始化,并且我希望发出use MyClass 的主程序能够为该初始化过程提供一个参数。

这是一个带有类变量的类的工作示例:

package MyClass;
use strict;
use warnings;

# class variable ('our' for package visibility)                                                                 
#                                                                                                               
our $class_variable = 3;  # Would like to bind to a variable                                                    

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

sub method {
    my $self = shift;
    print "class_variable: $class_variable\n";
    ++$class_variable; # prove that other instances will see this change                                        
}

这是一个演示:

#!/usr/bin/perl                                                                                                 

use strict;
use warnings;
use MyClass;

my $foo = MyClass->new();
$foo->method(); # show the class variable, and increment it.

my $bar = MyClass->new();
$bar->method(); # this will show the incremented class variable.

主程序有没有办法为$class_variable 指定一个值?该值将在主程序的编译时已知。

【问题讨论】:

标签: perl oop initialization class-variables


【解决方案1】:

您还可以通过使用my 而不是our 声明变量来将其设为“私有”。在这种情况下,您必须提供一个类方法来对其进行初始化:

my $class_variable = 3;

sub initialize_variable {
    my ($class, $value) = @_;
    die "Ivalid value $value.\n" unless $value =~ /^[0-9]+$/;
    $class_variable = $value;
}

然后在程序中:

'MyClass'->initialize_variable(42);

【讨论】:

  • 看起来不错。我认为没有任何方法可以利用“使用”语句本身,是吗?例如use MyClass qw/42/; ?
  • @Chap 如果 MyClass 有一个名为 import 的子程序,则当 perl 遇到带有这些参数的 use 语句时将调用它:import("MyClass", 42)(参见 importuse
  • @Oktalist 美丽。这实际上是我的目的的最佳解决方案,因为它确保它发生在任何对象实例化之前。如果您想输入该答案作为答案,我会给您“正确答案”的荣誉。
  • 好的,谢谢。我更喜欢 choroba 的回答,除非你真的想要那种行为。
  • @Oktalist:除非有子程序MyClass:试试sub MyClass::new { bless {}, shift } sub MyClass { die } print MyClass->new
【解决方案2】:

使用import 设施:

package MyClass;

my $class_variable;

sub import
{
  (undef, my $new_class_variable) = @_;

  if (defined $class_variable and
      defined $new_class_variable and
      $class_variable ne $new_class_variable)
  {
    warn '$MyClass::class_variable redefined';
  }

  $class_variable = $new_class_variable if defined $new_class_variable;
}

use 模块时传递值:

use MyClass qw(42);

这并不完全是惯用的 Perl,但也不少见。函数中间的健全性检查应该给你一个提示,为什么它可能不是所有情况下的最佳方法。如果 MyClass 只应该是顶级脚本中的 used,您可以改为强制执行该健全性检查:

caller eq 'main' or die 'MyClass can only be used from package main';

【讨论】:

  • 我明白你关于也可以从另一个包中使用的观点。在我的例子中,我希望传递的参数是程序的名称,以便 MyClass 可以从数据库中读取一些特定于程序的元数据。绝对是只有从'main'中使用它才有意义的情况。 (我认为。)
  • @Chap 你不能用$0吗?
  • 参数更准确地说是指将使用的应用程序协议。虽然目前程序和协议之间是一对一的关系,但我不想强求。 (如果这有意义的话。)
【解决方案3】:
$MyClass::class_variable = "some value";

【讨论】:

    【解决方案4】:

    你也可以使用 Class 方法:

    例如:

    package myclass;
    
    our $class_variable = 5;
    
    sub myclass_method{
    
        my ($class, $new_class_variable_value) = @_;
    
        if( $class_variable != $new_class_variable_value )
        {
            ## set the new value of the class/package variable
            $class_variable = $new_class_variable_value;
        }
    }
    

    在您的脚本中,您可以通过以下方式调用它:

    myclass::myclass_method('myclass', 7);
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-08-25
      • 2013-04-05
      • 1970-01-01
      • 2013-07-04
      • 1970-01-01
      • 2016-11-03
      • 2015-04-16
      相关资源
      最近更新 更多