在Perl中,子类在基类中对方法进行别名的正确方法是什么?

Sin*_*nür 12 oop perl goto

我只是讨厌如何调用CGI :: ApplicationCGI对象访问器query.

我希望我的实例类能够使用一个名为的访问器cgi来获取CGI与我的CGI::Application子类的当前实例相关联的对象.

这是我正在做的事情的一个独立的例子:

package My::Hello;

sub hello {
    my $self =shift;
    print "Hello @_\n";
}

package My::Merhaba;

use base 'My::Hello';

sub merhaba {
    goto sub { shift->hello(@_) };
}

package main;

My::Merhaba->merhaba('StackOverflow');
Run Code Online (Sandbox Code Playgroud)

这是我认为它应该工作,我不能看到任何问题(比如说,如果我想继承My::Merhaba:子类不需要知道任何事情merhaba).

写作会更好/更正确吗?

sub merhaba {
    my $self = shift;
    return $self->hello(@_);
}
Run Code Online (Sandbox Code Playgroud)

使用goto &NAME方法名称别名的优点/缺点是什么?有没有更好的办法?

注意:如果你有回应的冲动goto是邪恶不要这样做,因为Perl的使用与goto你的想法不同.

Eri*_*rom 10

你的方法goto是正确的,因为它将确保caller/ wantarray等继续正常工作.

我会像这样设置新方法:

sub merhaba {
    if (my $method = eval {$_[0]->can('hello')}) {
        goto &$method
    } else { 
        # error code here
    }
}
Run Code Online (Sandbox Code Playgroud)

或者,如果您不想使用继承,可以从调用代码将新方法添加到现有包中:

*My::Hello::merhaba = \&My::Hello::hello;  
   # or you can use = My::Hello->can('hello');
Run Code Online (Sandbox Code Playgroud)

然后你可以打电话:

My::Hello->merhaba('StackOverflow');
Run Code Online (Sandbox Code Playgroud)

并获得所需的结果.

无论哪种方式都可行,继承路由更易于维护,但将方法添加到现有包将导致更快的方法调用.

编辑:

正如评论中所指出的,有一些情况是全局赋值将与继承发生冲突,所以如果有疑问,请使用第一种方法(在子包中创建一个新方法).

Michael Carman建议将这两种技术结合到一个自我重新定义的功能中:

sub merhaba {
    if (my $method = eval { $_[0]->can('hello') }) {
        no warnings 'redefine';
        *merhaba = $method;
        goto &merhaba;
    }
    die "Can't make 'merhaba' an alias for 'hello'";
}
Run Code Online (Sandbox Code Playgroud)

  • 我做了一个小的改进,并将其作为另一个答案提交:http://stackoverflow.com/questions/2266865#2269580我建议把它拉进这个. (2认同)