捕获Perl中的未定义值访问

时间:2017-06-21 15:13:46

标签: perl member-variables

如何捕获成员变量的访问权限?

$Class1->{Class2}

如果Class2字段不存在,是否可以从内部函数中捕获它?

2 个答案:

答案 0 :(得分:1)

你可以,但你可能不应该。这里的问题是 - 如果你直接访问类中的变量...那么你就可以。你可以通过几种解决方法来防止这种情况 - 这就是Moose之类的东西。

还有一些像内而外的对象(我认为不再是常见的做法) - 或Perl Best Practice在几年前提倡它们或者使用匿名哈希来保持状态。

但失败了 - 为什么不使用访问器,并使用' AUTOLOAD'自动生成一个访问器。

#!/usr/bin/env perl

package MyClass;
use strict;
use warnings; 

use vars '$AUTOLOAD';
sub AUTOLOAD { 
   my ( $self ) = @_; 

   my $subname = $AUTOLOAD =~ s/.*:://r;

   if ( $self -> {$subname} ) { 
      return $self -> {$subname}; 
   }
   warn "Sub called $subname was called\n";
   return "$subname"; 
}

sub new {
   my ( $class ) = @_;
   my $self = {};
   bless $self, $class;
}

package main; 
use strict;
use warnings;

my $object = MyClass -> new; 
$object -> {var} = "fleeg";

print "Undef fiddle was: ", $object -> fiddle,"\n";
print "But 'var' was: ", $object -> var,"\n";

这有同样的问题,因为更改方法名称可能会导致事情中断。但它的优点是你可以处理无效的'方法调用,但你喜欢。

但真的 - 明确'得到'和'设置'对于大多数用例来说,方法是更好的选择。

答案 1 :(得分:0)

您可以通过提供包含类/实例变量的正确getter / setter方法来实现此目的。永远不应该直接访问内部,特别是从类本身外部访问(除了保持特定属性的实际方法之外,在类中也不这样做是明智的。这是一个非常基本的例子:

use warnings;
use strict;

package A;

sub new {
    my ($class, %args) = @_;
    my $self = bless {}, $class;

    $self->x($args{x});
    $self->y($args{y});

    return $self;
}
sub x {
    my ($self, $x) = @_;
    $self->{x} = $x if defined $x;
    return $self->{x} // 1;
}
sub y {
    my ($self, $y) = @_;
    $self->{y} = $y if defined $y;
    return $self->{y} // 2;
}

package main;

my $obj = A->new(x => 5, y => 3);

print $obj->x ."\n";
print $obj->y ."\n";

现在,您可以轻松地执行print $obj->{x},但这就是您的问题所在。当代码比这复杂得多时会发生什么,并且出于某种原因,您希望将x属性名称更改为foo,但保留x()方法? $obj->{x}现在将undef为未设置。

始终使用提供的方法来访问类/对象的属性。像这样的封装是面向对象编程的主要内容。