Perl 子例程参考
我有一组字段,每个字段都有不同的验证规则集。
我已经放置了用于验证哈希引用的子例程引用。
目前它在我的构造函数中,但我想将它从私有子构造函数中取出。
我已经按如下方式完成了
sub new {
my $class = shift;
my $self = {@_};
$class = (ref($class)) ? ref $class : $class;
bless($self, $class);
$self->{Validations} = {
Field1 => {name => sub{$self->checkField1(@_);},args => [qw(a b c)]}
Field2 => {name => sub{$self->checkField2(@_);},args => {key1, val1}}
..
..
..
..
};
return $self;
}
现在我想从我的构造函数中取出所有这些验证规则,并想做一些如下所示的事情,以便我可以更好地控制基于类型字段的验证规则。(假设一些规则是在一组字段中很常见,我可以通过覆盖字段的值来覆盖其他规则的规则。)
bless($self, $class);
$self->{Validations} = $self->_getValidation($self->{type});
return $self;
}
sub _getValidation{
my ($self,$type) = @_;
my $validation = {
Field1 => {name => sub {$self->checkField1(@_);}, args => {key1 => val1}},};
return $validation;
}
但我得到 Can't use string ("") as a subroutine ref while "strict refs" in use at...
谁能告诉我为什么子引用会出现这种行为。如果我检查我的名字键,它会变成 null 或 sub {DUMMY};
I have a set of fields with each field having different set of validation rules.
I have placed the subroutine reference for validating a hash-ref.
Currently its in my constructor, but I want to take it out of my constructor in a private sub.
I have done it as below
sub new {
my $class = shift;
my $self = {@_};
$class = (ref($class)) ? ref $class : $class;
bless($self, $class);
$self->{Validations} = {
Field1 => {name => sub{$self->checkField1(@_);},args => [qw(a b c)]}
Field2 => {name => sub{$self->checkField2(@_);},args => {key1, val1}}
..
..
..
..
};
return $self;
}
Now I want to take out all this validation rules out of my constructor and want to do some thing like below, so that I have some better control over my validation rules based on types fields.(Say some rules are common in one set of fields and I can overwrite rules for other rules just by overwriting the values of fields.)
bless($self, $class);
$self->{Validations} = $self->_getValidation($self->{type});
return $self;
}
sub _getValidation{
my ($self,$type) = @_;
my $validation = {
Field1 => {name => sub {$self->checkField1(@_);}, args => {key1 => val1}},};
return $validation;
}
But I am getting Can't use string ("") as a subroutine ref while "strict refs" in use at...
Can anybody tell me why is this behavior with sub ref. If I check my name key, its coming to be null or sub {DUMMY};
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
在我看来,你正在差点重新发明 Moose 。考虑使用 Moose 而不是构建类似但不太有用的东西。
该错误消息意味着您正在代码需要代码引用的位置传递字符串。获取堆栈跟踪以找出错误来自何处。
您可以通过使用 Carp::Always、覆盖
$SIG{__DIE__}
处理程序来生成堆栈跟踪或在代码中插入Carp::confess
来实现此目的。这是一个 sigdie 解决方案,将其粘贴到您的代码中,它将在模块初始化之前运行:
您可能需要将其放在
BEGIN
块中。我真的很想劝阻您不要采用这种方法来构建对象。您很高兴地祝福作为对象一部分传递给构造函数的任何随机垃圾!你愉快地触及你的物体内部。字段验证规则*不不属于构造函数——它们属于属性修改器。
如果您必须使用 DIY 对象,请清理您的做法:
所有这些代码都非常好,但您必须为每个属性重复您的属性代码。这意味着大量容易出错的样板代码。您可以通过学习使用闭包或字符串 eval 动态创建方法来解决此问题,或者您可以使用 Perl 的众多类生成库之一,例如 Class::Accessor、Class::Struct、Accessor::Tiny 等。
或者你可以学习[驼鹿][3]。 Moose 是一个新的对象库,它已经取代了 Perl OOP 实践。与经典 Perl OOP 相比,它提供了一组强大的功能并显着减少了样板代码:
It looks to me like you are getting close to reinventing Moose poorly. Consider using Moose instead of building something similar, but less useful.
The error message means that you are passing in a string in a place where your code expects a code reference. Get a stack trace to figure out where the error is coming from.
You can do this by using Carp::Always, overriding the
$SIG{__DIE__}
handler to generate a stack trace, or inserting aCarp::confess
into your code.Here's a sigdie solution, stick this in your code where it will run before your module initialization:
You may need to put it in a
BEGIN
block.I'd really like to discourage you from taking this approach to building objects. You happily bless any random crap passed in to the constructor as part of your object! You blithely reach into your object internals. Field validation rules *do not belong in the constructor--they belong in the attribute mutators.
If you must use a DIY object, clean up your practices:
All this code is very nice, but you have to repeat your attribute code for every attribute. This means a lot of error-prone boilerplate code. You can get around this issue by learning to use closures or string eval to dynamically create your methods, or you can use one of Perl's many class generation libraries such as Class::Accessor, Class::Struct, Accessor::Tiny and so forth.
Or you can learn [Moose][3]. Moose is the new(ish) object library that has been taking over Perl OOP practice. It provides a powerful set of features and dramatically reduces boilerplate over classical Perl OOP:
我还没有阅读您所拥有的所有内容,但这让我印象深刻:
通常,当您创建一个新对象时,用户不会将
$self
作为对象之一传递。这就是你正在创造的。您通常会看到类似这样的内容:
现在,
$self
不必像上面的示例那样是对哈希的引用。它可以是对数组的引用。或者也许是一个函数。但是,它通常是一个参考。要点是,用户不会传入$self
,因为它是由您的new
子例程创建的。您也不必检查
$class
的值,因为该值是在调用new
子例程时给出的。如果您想在私有类中进行验证(顺便说一下,这是一个好主意),您可以在
bless
之后执行此操作:I haven't read everything you had, but this struck me:
Normally, when you create a new object, the user doesn't pass
$self
as one of the objects. That's what you're creating.You usually see something like this:
Now,
$self
doesn't have to be a reference to a hash as in the above example. It could be a reference to an array. Or maybe to a function. But, it's usually a reference. The main point, is that the user doesn't pass in$self
because that's getting created by yournew
subroutine.Nor, do you have to check the value of
$class
since that's given when thenew
subroutine is called.If you want to do your verification in a private class (an excellent idea, by the way), you can do so after the
bless
: