Reputation: 67
I have a package I created that is meant to return the object's specified attribute (shortened code)
package vendor_info;
my $vars;
sub new{
my $class = shift;
$vars = {
_servers => shift,
_locations => shift,
_favorite => shift,
_default_selection => shift,
_database => shift,
_DB => shift};
bless $vars, $class;
return $vars;
}
sub get_locations{
return $vars->{_locations};
}
sub get_database{
return $vars->{_database};
}
sub get_DB{
return $vars->{_DB};
}
My perl file receives an input parsed from the terminal but in this case, the variable $vendor is hard coded for testing. I have a list of objects in a hash, and I want to return the correct attribute according to the object. Some of the variables have been removed with placeholders.
$vendor = "atrena";
my %vendor_hash = (
"atrena" => new vendor_info("Variable_server","Variable_location","Advanced_CDC|CDC dftso|DFT|gui|GUI|adv_checker|Lint|spl-view-only|view-only-GUI","adv_checker","database","DB"),
"ansys" => new vendor_info("Variable","Location","agppi|agppi|ane3fl|ane3fl|ansys|ansys|ensemble_gui|ensemble_gui|hfss_desktop|hfss_desktop|hfss_gui|hfss_gui|hfss_solve|hfss_solve|hfsshpc_pack|hfsshpc_pack|optimetrics|optimetrics|q3d_desktop|q3d_desktop|rdacis|rdacis|struct|struct","ane3fl","database", "db"),
"coventor" => new vendor_info("var","location","COV_ZsplatViewer|Viewer|COV_VoxelModeler|Voxel-Modeler|MEMSp_Import_Package|Import-Package|MEMSp_Innovator_Plugin|Innovator-Plugin|MEMSp_MATLAB_Simulation|MATLAB-Simulation|MEMSp_Platform|Platform|MTI_AutoBuilder|Auto-Builder|MTI_Catapult|Catapult|MTI_CoventorWare|Coventor-Ware|MTI_Memcap|Memcap|MTI_PreProcessor|PreProcessor","database","db","db")
);
$vendor_object = $vendor_hash{$vendor};
print Dumper( $vendor_object);
$foodb = $vendor_object -> get_database();
The dumper is printing the correct information, however, when I call get_database(), the database called is always the attribute from the last object in the list, which in this case is coventor. The same could be said for any of the sub routine getters.
How do I call the correct attribute for the correct object?
Upvotes: 3
Views: 121
Reputation: 126722
In addition to other people's points, you will need to add a true statement at the end of your .pm
file
This is how I would write your application
package VendorInfo;
use strict;
use warnings 'all';
sub new {
my $class = shift;
my $self;
@{$self}{qw/
_servers
_locations
_favorite
_default_selection
_database _DB
/} = @_;
return bless $self, $class;
}
sub get_locations {
my $self = shift;
return $self->{_locations};
}
sub get_database {
my $self = shift;
return $self->{_database};
}
sub get_DB {
my $self = shift;
return $self->{_DB};
}
1;
use strict;
use warnings 'all';
use VendorInfo;
use Data::Dumper;
my $vendor = 'atrena';
my %vendor_hash = (
atrena => VendorInfo->new(
'Variable_server',
'Variable_location',
'Advanced_CDC|CDC dftso|DFT|gui|GUI|adv_checker|Lint|spl-view-only|view-only-GUI',
'adv_checker',
'database',
'DB',
),
ansys => VendorInfo->new(
'Variable',
'Location',
'agppi|agppi|ane3fl|ane3fl|ansys|ansys|ensemble_gui|ensemble_gui|hfss_desktop|hfss_desktop|hfss_gui|hfss_gui|hfss_solve|hfss_solve|hfsshpc_pack|hfsshpc_pack|optimetrics|optimetrics|q3d_desktop|q3d_desktop|rdacis|rdacis|struct|struct',
'ane3fl',
'database',
'db',
),
coventor => VendorInfo->new(
'var',
'location',
'COV_ZsplatViewer|Viewer|COV_VoxelModeler|Voxel-Modeler|MEMSp_Import_Package|Import-Package|MEMSp_Innovator_Plugin|Innovator-Plugin|MEMSp_MATLAB_Simulation|MATLAB-Simulation|MEMSp_Platform|Platform|MTI_AutoBuilder|Auto-Builder|MTI_Catapult|Catapult|MTI_CoventorWare|Coventor-Ware|MTI_Memcap|Memcap|MTI_PreProcessor|PreProcessor',
'database',
'db',
'db',
),
);
my $vendor_object = $vendor_hash{$vendor};
print Dumper $vendor_object;
my $foodb = $vendor_object->get_database;
print $foodb, "\n";
$VAR1 = bless( {
'_servers' => 'Variable_server',
'_default_selection' => 'adv_checker',
'_locations' => 'Variable_location',
'_database' => 'database',
'_DB' => 'DB',
'_favorite' => 'Advanced_CDC|CDC dftso|DFT|gui|GUI|adv_checker|Lint|spl-view-only|view-only-GUI'
}, 'VendorInfo' );
database
Upvotes: 4
Reputation: 85757
Dave Cross already answered your immediate question.
This is an example of a more idiomatic version of your code:
{
package VendorInfo;
use Moo;
for my $attr (qw(
servers
locations
favorite
default_selection
database
DB
)) {
has $attr => (
is => 'ro',
required => 1,
);
}
}
# main program
use strict;
use warnings;
use Data::Dumper;
my %vendor_hash = (
"atrena" => VendorInfo->new(
servers => "Variable_server",
locations => "Variable_location",
favorite => "Advanced_CDC|CDC dftso|DFT|gui|GUI|adv_checker|Lint|spl-view-only|view-only-GUI",
default_selection => "adv_checker",
database => "database",
DB => "DB",
),
"ansys" => VendorInfo->new(
servers => "Variable",
locations => "Location",
favorite => "agppi|agppi|ane3fl|ane3fl|ansys|ansys|ensemble_gui|ensemble_gui|hfss_desktop|hfss_desktop|hfss_gui|hfss_gui|hfss_solve|hfss_solve|hfsshpc_pack|hfsshpc_pack|optimetrics|optimetrics|q3d_desktop|q3d_desktop|rdacis|rdacis|struct|struct",
default_selection => "ane3fl",
database => "database",
DB => "db",
),
"coventor" => VendorInfo->new(
servers => "var",
locations => "location",
favorite => "COV_ZsplatViewer|Viewer|COV_VoxelModeler|Voxel-Modeler|MEMSp_Import_Package|Import-Package|MEMSp_Innovator_Plugin|Innovator-Plugin|MEMSp_MATLAB_Simulation|MATLAB-Simulation|MEMSp_Platform|Platform|MTI_AutoBuilder|Auto-Builder|MTI_Catapult|Catapult|MTI_CoventorWare|Coventor-Ware|MTI_Memcap|Memcap|MTI_PreProcessor|PreProcessor",
default_selection => "database",
database => "db",
DB => "db",
),
);
my $vendor = "atrena";
my $vendor_object = $vendor_hash{$vendor};
print Dumper($vendor_object);
print "The database is: ", $vendor_object->database, "\n";
Things of note:
vendor_info
to VendorInfo
. Lowercase module names are (informally) reserved for pragmata.has
helper function for declaring attributes. It also generates a constructor for me, so I don't have to write any boilerplate myself.method $object
or method class
, in your case new vendor_info
) is a bad idea because of its syntactic ambiguity. class->method
(here: VendorInfo->new
) is much better.'ro'
)) accessor, so client code can simply use $object->database
.Upvotes: 4
Reputation: 69224
You have $vars
as a lexical variable which is scoped to the file which contains your package. So there is only one instance of this variable and it will always contain the data for the last object that was set up.
I'm not sure where you picked up that approach, but it's not how Perl objects work at all. $vars
should be scoped to only exist within your constructor and your accessors should be using the object that is passed to them as their first argument (traditionally called $self
).
# Only pragmas should start with lower-case letters
package VendorInfo;
sub new{
my $class = shift;
my $vars = {
_servers => shift,
_locations => shift,
_favorite => shift,
_default_selection => shift,
_database => shift,
_DB => shift
};
return bless $vars, $class;
}
# Just one example accessor...
sub get_database{
my $self = shift;
return $self->{_database};
}
One more point, please use Class->new()
instead of the potentially problematic new Class
syntax that you are using in your code.
Upvotes: 7