我可以将对象方法替换为不同对象上的不同方法吗?

glt*_*lts 4 perl

用一个例子更容易解释:

my $o = SpecialEffects->new( "config" => 'a' );
my $p = SpecialEffects->new( "config" => 'b' );

$o->sound(); # aliased to fizz(); same as $o->fizz()
$p->sound(); # aliased to clonk(); same as $p->clonk()
Run Code Online (Sandbox Code Playgroud)

是否可以在Perl中执行此操作?也许使用一些typeglob或coderef技巧?

我试图保持SpecialEffects界面简单.我不想开始构建对象层次结构.该sound()方法是暴露的,只能稍微配置其行为.

我已经知道你可以使用别名,*sound = \&fizz;但据我所知,这是一个全局的东西,我希望它封装在对象中.

cha*_*aos 5

简单,简单,非魔法的方法是在SpecialEffects对象中存储方法名称,根据您想要发生的任何事情设置它,并从中调用它sound().

package SpecialEffects;

sub new {
    my $type = shift;
    my %options = @_;
    my $self = {};
    bless $self, $type;
    if($options{config} eq 'a') {
        $self->{sound_method} = 'fizz';
    } elsif($options{config} eq 'b') {
        $self->{sound_method} = 'clonk';
    }
    return $self;
}

sub sound {
    my $self = shift;
    my $method_name = $self->{sound_method};
    $self->$method_name();
}

sub fizz {
    print "fizz\n";
}

sub clonk {
    print "clonk\n";
}
Run Code Online (Sandbox Code Playgroud)

如果您想要更精灵,可以像方法名一样轻松地存储和使用coderefs.

package SpecialEffects;

sub new {
    my $type = shift;
    my %options = @_;
    my $self = {};
    bless $self, $type;
    if($options{config} eq 'a') {
        $self->{sound_code} = $self->can('fizz');
    } elsif($options{config} eq 'b') {
        $self->{sound_code} = $self->can('clonk');
    }
    return $self;
}   

sub sound {
    my $self = shift;
    my $code = $self->{sound_code};
    $self->$code();
}
Run Code Online (Sandbox Code Playgroud)