Search code examples
perlperl-module

I have a string with a package name. Is it possible to get a package variable?


in WithVar.pm:

package Test::WithVar;

our @desired_var = qw(1 2 3);

OtherPackage.pm:

package Test::OtherPackage;
use Test::WithVar;

sub test_get_var ($) {
    my $package_name = shift;

    #↓ How to do that ? Is it possible ? ↓
    return @{$package_name::desired_var};
}

# I know that I can access the desired_var with @Test::WithVar::desired_var,
# (explicitly typed package name, a 'bareword')
# but what if I have package name in a string ?

test_get_var('Test::WithVar');

Another solution (i guess) is to define a function in the WithVar package that will return our variable.

package Test::WithVar;

our @desired_var = qw(1 2 3);

sub return_desired_var ($) {
    my $self = shift;
    our @desired_var;
    return \@desired_var;
}

So now I can:

package Test::OtherPackage;
use Test::WithVar;

my $str = 'Test::WithVar';
print @{$str->return_desired_var()}, '\n';

But the problem is the inheritance. I need to inherit from WithVar and child modules will return WithVar::desired_var and I need $ChildPackage::desired_var.

package Test::ChildWithVar; use parent 'Test::WithVar';

our @desired_var = qw(4 5 6); # redefine variable in child module.

And if I write

package Test::OtherPackage;
use Test::ChildWithVar;

my $str = 'Test::ChildWithVar';

# This will print 1 2 3 of course, not 4 5 6.
print @{$str->return_desired_var()}, '\n'; 

So I need somehow to write universal method in Test::WithVar package:

package Test::WithVar;

our @desired_var = qw(1 2 3);

sub return_desired_var_universal ($) {
    my $self = shift;
    my $class = ref $self || $self;
    return $class::desired_var; #Somehow ?!
}

I know that I can use a hash and store package-specific variables in it instead of using 'our' variables. I know. But I need a solution with 'our', or the clear understanding that this is not possible.

Thanks.


Solution

  • You should use strict, for many reasons, the one concerning your case being explained here.

    You can disable the warning, use strict emits for the following code by

    # some code block
    {  
       ...
       no strict 'refs'; 
       return @{$package_name.'::desired_var'};
    }
    

    You should try to put what you really want to achieve in a seperate question and explain why you think, it could only be done with our variables.