I am vaguely confused a bit on different methods of passing certain arguments to the constructor type. I want to only pass a hash reference \%hash
, or a list foo => 1, bar => 1
but not both and croak
if anything else is passed i.e ( single elements, array reference )
.
For example, I pass my reference or list.. (This works for the way I do this)
my $obj = foo->new;
my $data = $obj->dump( \%hash );
my $data = $obj->dump( foo => 1, bar => 1 );
or
my $obj = foo->dump( \%hash );
my $obj = foo->dump( foo => 1, bar => 1 );
Package module:
package foo;
use strict;
use Carp;
use Scalar::Util qw/reftype/;
sub new { return bless {}, shift }
sub dump {
my $class = shift;
my $self = shift;
unless ( reftype( $self ) eq reftype {} ) {
croak("Constructor method not a hash type!");
}
}
1;
I've also thought about using the conditional operator ? :
here, but I can't get it to error properly.
my $self = reftype($_[0]) eq reftype {} ? shift : {@_};
Is there a better preferred way to do this?
We can look at the various ways your dump
method can be called.
If we pass a "hash list", the number of elements is even (@_ % 2 == 0
). Also, if at least one key-value pair is present, the first argument (a key) is a string, so not defined reftype $_[0]
holds.
If we pass a hash reference, then the argument list should only hold this reference, and no other values: @_ == 1
. The first argument will be a hash: reftype($_[0]) eq 'HASH'
.
So to put the arguments in a hash reference, one could do something like:
sub dump {
my $invocant = shift;
my $hashref;
if (@_ == 1 and reftype $_[0] eq 'HASH') {
$hashref = $_[0];
} elsif (@_ % 2 == 0 and (@_ == 0 or not defined reftype $_[0])) {
$hashref = +{ @_ };
} else {
croak "Unknown argument format: either pass a hashref, or an even-valued list";
}
...; # do something with $hashref
}
To find out if the $invocant
is the class name or an object, just ask it if it is blessed:
if (defined Scalar::Util::blessed $invocant) {
say "Yep, it is an object";
} else {
say "Nope, it is a package name";
}