# Hash Value
$hash{'name'} = 'Herk';
$self->get_name(); # Returns 'Herk'
Can someone help me fill in the blank about how I should do this?
As I understand it, doing it by hand would be something like:
my %hash;
sub get_name {
my $subname = (caller 0)[3];
$subname =~ s/.*::get_//;
print $hash{$subname},v10;
}
$hash{'name'} = 'Herk';
get_name;
But I believe the best way would be to resort to some CPAN module. I haven't done much OO programming but I think [mod://Class::Accessor] will fit.
--
David Serrano
Now ask the real question (see XY Problem).
It looks like you want to return the 'name' property of an object. Assuming that $hash is the object that was blessed to create the object instance then the following is probably what you want:
sub get_name {
my $self = shift;
return $self->{name};
}
Why not simply provide a 'get' method?
$self->get ('name');
...
sub get {
my ($self, $param) = @_;
return undef if ! exists $self->{$param};
return $self->{$param};
}
Alternatively there are CPAN modules such as [mod://Class::MethodMaker] that will generate getters and setters for you given a list of properties.
I just wanted to use a more explicit method name rather than pass a value all the time. I figured it, cannot be that hard right?
Let me take a look at Class:MethodMaker and see if that gives me what I want...
Thanks!
If you don't want to use something like [cpan://Class::MethodMaker], it's pretty trivial to do this sort of thing yourself.
package Foo;
use strict;
use warnings;
foreach my $name(qw(foo bar baz quux narf)) {
no strict 'refs';
*{ 'Foo::get_' . $name } = sub {
my $self = shift;
return $self->{$name};
};
}
Constructing the equivelent set_* methods is left as an exercise for the reader. :)
That's more correct (and, in my opinion, readable) as:
return unless exists $self->{$param};Beware of undef in list context.
You should probably ask yourself whether this is really the way you want to go. First of all, you don't feel like defining one hundred methods for one hundred hash keys. But say you find a way, you still have at least one hundred different calls, so are you ok with that? It will be very difficult to let your program grow.
Why don't you try to understand 'objects' (that is, blessed references) first, define a getter, a setter and making the key as one of the arguments. The getter and setter methods can validate the input for you.
If you really insist and if you are prepared to follow the narrow, steep, winding path you could use a method called AUTOLOAD; this method will be called in case the requested method can not be found. It allows you to examine the method that was called, so you can extract the desired key from the method. In fact, the O'Reilly book "Perl Objects, References and Modules", chapter 11 (or its successor "Intermediate Perl") describes how to do just what you want.
Luckily friedo made an excellent suggestion Re^3: Link methods to hash values and it was not a lot of work and avoids dealing with the internals of Perl Objects.
Solution: make your hashes objects of a class that implements that behaviour. Ah, you are already on that path. I see $self in your code. But how are %hash and $self supposed to be related?
package myHash;
sub new { bless {}, shift }
sub AUTOLOAD {
# next two lines just to see what's happening...
print '@_ = ('.join(', ',map{"'$_'"}@_), ")\n";
print "\$AUTOLOAD = $AUTOLOAD\n";
my ($self,$value) = @_;
(my $key = $AUTOLOAD) =~ s/.*:://;
$self->{$key} = $value if $value;
$self->{$key};
}
1;
Now you can
#!/usr/bin/perl
use myHash;
$thingy = myHash->new(foo => 'bar');
print $thingy->foo,"\n";
print $thingy->foo('baz'),"\n";
print $thingy->age('ageless'),"\n";
__END__
#output:
@_ = ('myHash=HASH(0x8166c28)')
$AUTOLOAD = myHash::foo
@_ = ('myHash=HASH(0x8166c28)', 'baz')
$AUTOLOAD = myHash::foo
baz
@_ = ('myHash=HASH(0x8166c28)', 'ageless')
$AUTOLOAD = myHash::age
ageless
@_ = ('myHash=HASH(0x8166c28)')
$AUTOLOAD = myHash::DESTROY
Note the last two lines - since our myHash package doesn't have a method called DESTROY, the AUTOLOAD routine is called to handle DESTROY during global destruction (at program's end). See [doc://perlobj].
But you don't have to roll your own, There are some modules at CPAN which implement autogeneration of accessors, getters/setters (for instance, [mod://Class::Accessor], [mod://Class::MethodMaker], ...), then there's [mod://Spiffy] which provides some other nifty features.
--shmem
_($_=" "x(1<<5)."?\n".q·/)Oo. G°\ /
/\_¯/(q /
---------------------------- \__(m.====·.(_("always off the crowd"))."·
");sub _{s./.($e="'Itrs `mnsgdq Gdbj O`qkdq")=~y/"-y/#-z/;$e.e && print}
perlmonks.org content © perlmonks.org and chromatic, friedo, GrandFather, Herkum, Hue-Bond, jeteve, lyklev, shmem, tinita
prlmnks.org © 2006 edmund von der burg (eccles & toad)
v 0.03