Reputation: 4425
I have this script
use strict;
use warnings;
use Data::Dumper;
package Foo;
sub new {
bless { 'a' => 1,
'b' => sub { return "foo" }
}, $_[0]
};
my $foo = Foo->new;
print $foo->b()."\n";
And when I run it I get Can't locate object method "b" via package "Foo"
Doesnt this code create an anonymous object so I could call the function b
?
Upvotes: 2
Views: 118
Reputation: 386541
In Perl, method invocation always involves a package.
$foo
is blessed into Foo
, so $foo->b
calls &Foo::b
(or the &b
of a package from which Foo
inherits).
I have no idea why you think it would call &{ $foo->{ b } }
. Objects don't even need to be hashes.
To make b
specific to the object, you could add the following to Foo
:
sub b { $_[ 0 ]{ b }->( @_ ) }
If you want hide b
from stack traces and from caller
, you could use
sub b { goto &{ $_[ 0 ]{ b } }; }
Demo:
use v5.14;
use warnings;
{
package Foo;
sub new {
my $class = shift;
return bless( { @_ }, $class );
}
sub b { $_[ 0 ]{ b }->( @_ ) }
}
my $foo1 = Foo->new( b => sub { "foo" } );
my $foo2 = Foo->new( b => sub { $_[1] } );
say $foo1->b( 123 ); # foo
say $foo2->b( 123 ); # 123
Upvotes: 2
Reputation: 1
If you want to ceate an anonymous object, with methods from hash keys something like this
my $obj; $obj = Plack::Util::inline_object(
b => sub { $obj->{_b} },
_b => 'foo',
));
This will give you $obj->{_b} and $obj->b both returning 'foo'
$obj->{b}() and $obj->{b}->() also work
There are multiple ways to do it, Plack::Util::inline_object is just the one I last used.
Upvotes: 0
Reputation: 946
In your code, b
is not a method, it's a key of the hashref on which your object is based. If you really want to address it that way, you'd do it this way:
print $foo->{b}, "\n";
But you (probably) don't want to do that. One of the strengths of object-oriented programming is keeping other parts of your program from reaching into your objects and manipulating them directly. Instead, you (probably) want to create methods for accessing your objects' attributes:
Package Foo;
sub new { bless {'a' => 1, 'b' => 2, ...}, $_[0]; }
sub b { my $self = shift; return $self->{b}; }
and so on.
Upvotes: 5