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
bis a hash key, not a method. So to call the sub you need to extract from the hash first like this:print $foo->{b}()."\n";