在 Perl 中,子类为基类中的方法添加别名的正确方法是什么?
我只是讨厌 CGI::Application 的 CGI< 访问器/code> 对象称为
查询
。
我希望我的实例类能够使用名为 cgi
的访问器来获取与我的 CGI::Application
当前实例关联的 CGI
对象代码>子类。
这是我正在做的事情的一个独立示例:
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');
这正在按我认为应该的方式工作,我看不到任何问题(比如说,如果我想从 My::Merhaba
继承:子类需要对merhaba
一无所知)。
会更好/更正确吗
sub merhaba {
my $self = shift;
return $self->hello(@_);
}
写一下What are the Advantages/disadvantages of using goto & ;NAME
是为了给方法名起别名吗?有更好的办法吗?
注意:如果您想用 goto 进行响应,goto
是邪恶的,请不要这样做,因为 Perl 的 goto
的使用code> 与您的想法不同。
I simply hate how CGI::Application's accessor for the CGI
object is called query
.
I would like my instance classes to be able to use an accessor named cgi
to get the CGI
object associated with the current instance of my CGI::Application
subclass.
Here is a self-contained example of what I am doing:
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');
This is working as I think it should and I cannot see any problems (say, if I wanted to inherit from My::Merhaba
: Subclasses need not know anything about merhaba
).
Would it have been better/more correct to write
sub merhaba {
my $self = shift;
return $self->hello(@_);
}
What are the advantages/disadvantages of using goto &NAME
for the purpose of aliasing a method name? Is there a better way?
Note: If you have an urge to respond with goto
is evil don't do it because this use of Perl's goto
is different than what you have in mind.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
您使用
goto
的方法是正确的,因为它将确保caller
/wantarray
等保持正常工作。我会像这样设置新方法:
或者,如果您不想使用继承,则可以从调用代码将新方法添加到现有包中:
然后您可以调用:
并获得所需的结果。
无论哪种方式都可以,继承路线更易于维护,但将方法添加到现有包中会导致更快的方法调用。
编辑:
正如评论中所指出的,在某些情况下,glob 赋值会与继承发生冲突,因此如果有疑问,请使用第一种方法(在子包中创建新方法)。
Michael Carman 建议将这两种技术组合成一个自我重新定义的函数:
Your approach with
goto
is the right one, because it will ensure thatcaller
/wantarray
and the like keep working properly.I would setup the new method like this:
Or if you don't want to use inheritance, you can add the new method to the existing package from your calling code:
then you can call:
and get the desired result.
Either way would work, the inheritance route is more maintainable, but adding the method to the existing package would result in faster method calls.
Edit:
As pointed out in the comments, there are a few cases were the glob assignment will run afoul with inheritance, so if in doubt, use the first method (creating a new method in a sub package).
Michael Carman suggested combining both techniques into a self redefining function:
您可以通过操作符号表为子例程设置别名:
可以找到一些示例
You can alias the subroutines by manipulating the symbol table:
Some examples can be found here.
我不确定正确的方法是什么,但 Adam Kennedy 在 方法::别名 (点击这里直接进入源码)。
I'm not sure what the right way is, but Adam Kennedy uses your second method (i.e. without
goto
) in Method::Alias (click here to go directly to the source code).这是 Quick-n-Dirty 与使用
UNIVERSAL::can
的少量间接的组合。在这个包中您将有一个名为“merhaba”的子项目,它的别名是
My::Hello::hello
。您只是说,无论这个包在hello
名称下执行的操作,它都可以在merhaba
名称下执行。然而,这还不够,因为某些代码装饰器可能会更改
*My::Hello::hello{CODE}
指向的 sub。在这种情况下,正如分子所暗示的那样,Method::Alias
可能是指定方法的适当方式。但是,如果它是一个控制良好的库,您可以同时控制父类别和子类别,那么上面的方法就更精简。
This is sort of a combination of Quick-n-Dirty with a modicum of indirection using
UNIVERSAL::can
.And you'll have a sub called "merhaba" in this package that aliases
My::Hello::hello
. You are simply saying that whatever this package would otherwise do under the namehello
it can do under the namemerhaba
.However, this is insufficient in the possibility that some code decorator might change the sub that
*My::Hello::hello{CODE}
points to. In that case,Method::Alias
might be the appropriate way to specify a method, as molecules suggests.However, if it is a rather well-controlled library where you control both the parent and child categories, then the method above is slimmmer.