0

次の問題があります。間違った方法で解決しようとしている可能性があります。正しい方法で解決する方法を教えていただければ幸いです。

実際のオブジェクト クラス (ref($self)) に基づいてパッケージ変数にアクセスするメソッドを持つ基本クラスがあります。

#!/usr/bin/env perl

my $var = SubClass->new();
$var->method();

package BaseClass;

sub new { construct... }
sub method { 
   my $self = shift;

   # in this method I wan to get values from 'our %VAR' of the children class or ref($self) class, something like that:
   return ${ref($self)::VAR}{k1}; 

   # of course I can create a method and do it in the following way but I am not sure that it's a good idea
   return $self->get_var()->{k1};
}
sub get_var { die "Imaplement in children"; }

package SubClass;

use base 'BaseClass';

our %VAR = (k1 => 'smth', k2 => 'smth', ...);
sub get_var { return \%VAR } # don't like this idea

1;
4

1 に答える 1

3

ソリューションを使用するの%{ref($self)::VAR}が最も簡単な場合もありますが、偏執的なプログラマーにはいくつかのチェックが含まれます。

# Accessing %__PACKAGE__::VAR:
# I hope that I'm not in a subclass,
#    because that would change the value reported by `ref($self)`
#    and I can't be bothered to search @ISA manually...

unless (defined ref $self) {
   die "\$self is not a reference!";
}
if (ref $self ~~ [qw/SCALAR ARRAY HASH
   CODE REF GLOB LVALUE FORMAT IO VSTRING Regexp /]) {
   die "\$self is not an object!";
}
no strict 'refs'; # Hehe, I can't use strict here :S
unless (%{ref($self).'::VAR'}) {
   warn "Umm, this hash is empty."
      . "I don't know if I just created it, or it is meant to be that way.";
}
return ${ref($self).'::VAR'}{k1};

結論として、アクセサー メソッドを使用すると、繰り返しが省略されるだけでなく、より安全になり、ハッキングが少なくなり、オブジェクト指向が大幅に向上します。

sub return_var {
   # We know that we are in the right package.
   # We know we are accessing the correct hash.
   # It is irrelevant whether I call this method
   #    from the package/class or from an object.
   # And I'm glad to take the method performance penalty
   #    in exchange for clear code.
   return \%VAR;
}

結論 2 では、それを行う方法は複数あります。そして Perl には、「正しい」方法はありません。2 番目のソリューションがより洗練されている理由は理解できるかもしれませんが。

于 2012-08-01T09:38:20.787 に答える