如何解析传递给定义为在 Perl 中接受 2 个参数的子例程的一个参数
How do I resolve one argument passed to a subroutine defined to accept 2 parameters in Perl
我正在创建一个新对象如下:
my $new_obj = new P_module({key => 'abc'});
P_module的构造函数定义如下:
sub new {
my ($pkg, $input) = @_;
my $obj = {};
bless ($obj, ref($pkg)||$pkg);
$obj->{key} = $input->{key};
}
据我所知,由于散列作为参数传递给 new,因此它将表示为 2 元素数组。所以,pkg
应该是 key
而 input
应该是 abc
。那么,obj
是如何掌握一把钥匙 key
的,$input->{key}
又是什么意思呢?
周围的大括号创建一个哈希 reference 或 hashref,这是一个单一的标量。参数值为
$pkg
— 包含包的名称,可能是 "P_module"
$input
— 引用提供的散列
代码 $input->{key}
访问与键 "key"
关联的值,该键由调用者提供
my $new_obj = new P_module({key => 'abc'});
这样写比较好
my $new_obj = P_module->new({key => 'abc'});
您可以添加另一个密钥,如
my $new_obj = P_module->new({key => 'abc', other => 'unused'});
与 "key"
关联的值被复制到对象的状态
$obj->{key} = $input->{key};
请注意,Perl 子例程 return 最后一个表达式的值,因此您的代码有错误。您希望 P_module::new
的最后一行是
bless ($obj, ref($pkg)||$pkg);
因为这将 return 可用于调用其他方法的受祝福对象,例如、
my $new_obj = new P_module({key => 'abc'});
print $new_obj->other_method_that_you_must_define(), "\n";
首先,
my $new_obj = new P_module({ key => 'abc' });
最好写成
my $new_obj = P_module->new({ key => 'abc' });
这是
的缩写
my %anon = ( key => 'abc' );
my $new_obj = P_module->new(\%anon);
进行方法调用时,调用者(->
的剩余部分)作为第一个参数传递。这意味着 $pkg
是字符串 P_module
,而 $input
是 { key => 'abc' }
.
返回的引用
由于 $input
是对散列的引用,$input->{key}
从引用的散列中获取具有键 key
的元素的值。
我会怎么写:
sub new {
my ($class, %args) = @_;
my $self = bless({}, $class); # If base class.
#my $self = $class->SUPER::new(); # If inheriting.
$self->{key} = $args{$key};
return $self;
}
my $obj = P_module->new( key => 'abc' );
调用者不需要散列,也没有理由支持$existing_obj->new
。它还使用更多标准名称 $class
和 $self
.
你有这样的原因吗:
bless ($obj, ref($pkg)||$pkg);
而不是这个?
bless ($obj, $pkg);
如果不是,那么我假设您是从某处的其他代码中剪切并粘贴的。你可能想要的是后者。
ref($pkg)||$pkg
允许您这样做:
my $new_object = $existing_obj->new;
而不是
my $new_object = new Classname;
既然你可能不需要这样做,那就坚持使用
bless ($obj, $pkg);
当您调用方法时,对象本身会在幕后传递;或者,如果 sub 使用 bless 则它是构造函数,而是传递 class 名称。因此,任何方法都会接收该对象或 class 名称作为其第一个参数。其余的是显式传递给方法的参数。
你传递一个散列引用{...}
,什么是标量。因此,它被分配给 $input
,假设 "quitely" 通过 class 名称被分配给 $pkg
。
该接口的构造函数,带有哈希引用,通常简单地写为
sub new {
my ($class, $input) = @_;
my $self = { %$input };
return bless $self, $class;
}
其中 return
可以省略,因为最后评估语句的 return 是 returned。最后两行可以写成return bless { %$input }, $class;
,一个(匿名的)hashref被初始化,blessed到它的包$class
中(所以它是一个对象),然后returned.
请注意,您不必传递哈希引用;一个简单的散列使得界面更清晰。如果可能还有其他参数,则需要使用参考,
使解析所有这些成为可能。
但是,您通常希望处理参数。首先,您 必须 检查它们是否符合您的 class 支持的内容,而不是盲目地将用户传递的键分配给属性。如果您提供默认值,然后计算默认值,如果需要检查值等。
这种数据初始化有时会被拆分成一个单独的子程序。例如
sub new {
my ($class, $input) = @_;
my $self = {};
bless $self, $class; # $self is an object now
$self->_init($input); # on which methods can be called
return $self;
}
sub _init {
my ($self, $args) = @_;
# Check arguments, work out defaults (etc),
# then assign to self as appropriate
%$self = %$args;
}
其中代码通过引用写入 "back",以便更新 new
中的 $self
。
这应该与普通方法调用一起使用
my $new_obj = P_module->new({key => 'abc', other => '...'});
和不使用间接表示法 new P_module
。构造函数,主要称为 new
(只是根据习惯——你可以随意称呼它),是一个普通的子特殊,只是因为它 bless
是一个引用(通常是一个散列引用),因此被传递class 名称而不是对象。因此它 "knows" 它的包并且是一个对象。
文学:perlmod (a class is a package), tutorial perlootut, and reference perlobj.
一旦您熟悉了 Perl 的内置面向对象功能(我建议您这样做),有许多模块可以使所有这些(以及更多)操作变得更容易。
我正在创建一个新对象如下:
my $new_obj = new P_module({key => 'abc'});
P_module的构造函数定义如下:
sub new {
my ($pkg, $input) = @_;
my $obj = {};
bless ($obj, ref($pkg)||$pkg);
$obj->{key} = $input->{key};
}
据我所知,由于散列作为参数传递给 new,因此它将表示为 2 元素数组。所以,pkg
应该是 key
而 input
应该是 abc
。那么,obj
是如何掌握一把钥匙 key
的,$input->{key}
又是什么意思呢?
周围的大括号创建一个哈希 reference 或 hashref,这是一个单一的标量。参数值为
$pkg
— 包含包的名称,可能是"P_module"
$input
— 引用提供的散列
代码 $input->{key}
访问与键 "key"
关联的值,该键由调用者提供
my $new_obj = new P_module({key => 'abc'});
这样写比较好
my $new_obj = P_module->new({key => 'abc'});
您可以添加另一个密钥,如
my $new_obj = P_module->new({key => 'abc', other => 'unused'});
与 "key"
关联的值被复制到对象的状态
$obj->{key} = $input->{key};
请注意,Perl 子例程 return 最后一个表达式的值,因此您的代码有错误。您希望 P_module::new
的最后一行是
bless ($obj, ref($pkg)||$pkg);
因为这将 return 可用于调用其他方法的受祝福对象,例如、
my $new_obj = new P_module({key => 'abc'});
print $new_obj->other_method_that_you_must_define(), "\n";
首先,
my $new_obj = new P_module({ key => 'abc' });
最好写成
my $new_obj = P_module->new({ key => 'abc' });
这是
的缩写my %anon = ( key => 'abc' );
my $new_obj = P_module->new(\%anon);
进行方法调用时,调用者(->
的剩余部分)作为第一个参数传递。这意味着 $pkg
是字符串 P_module
,而 $input
是 { key => 'abc' }
.
由于 $input
是对散列的引用,$input->{key}
从引用的散列中获取具有键 key
的元素的值。
我会怎么写:
sub new {
my ($class, %args) = @_;
my $self = bless({}, $class); # If base class.
#my $self = $class->SUPER::new(); # If inheriting.
$self->{key} = $args{$key};
return $self;
}
my $obj = P_module->new( key => 'abc' );
调用者不需要散列,也没有理由支持$existing_obj->new
。它还使用更多标准名称 $class
和 $self
.
你有这样的原因吗:
bless ($obj, ref($pkg)||$pkg);
而不是这个?
bless ($obj, $pkg);
如果不是,那么我假设您是从某处的其他代码中剪切并粘贴的。你可能想要的是后者。
ref($pkg)||$pkg
允许您这样做:
my $new_object = $existing_obj->new;
而不是
my $new_object = new Classname;
既然你可能不需要这样做,那就坚持使用
bless ($obj, $pkg);
当您调用方法时,对象本身会在幕后传递;或者,如果 sub 使用 bless 则它是构造函数,而是传递 class 名称。因此,任何方法都会接收该对象或 class 名称作为其第一个参数。其余的是显式传递给方法的参数。
你传递一个散列引用{...}
,什么是标量。因此,它被分配给 $input
,假设 "quitely" 通过 class 名称被分配给 $pkg
。
该接口的构造函数,带有哈希引用,通常简单地写为
sub new {
my ($class, $input) = @_;
my $self = { %$input };
return bless $self, $class;
}
其中 return
可以省略,因为最后评估语句的 return 是 returned。最后两行可以写成return bless { %$input }, $class;
,一个(匿名的)hashref被初始化,blessed到它的包$class
中(所以它是一个对象),然后returned.
请注意,您不必传递哈希引用;一个简单的散列使得界面更清晰。如果可能还有其他参数,则需要使用参考, 使解析所有这些成为可能。
但是,您通常希望处理参数。首先,您 必须 检查它们是否符合您的 class 支持的内容,而不是盲目地将用户传递的键分配给属性。如果您提供默认值,然后计算默认值,如果需要检查值等。
这种数据初始化有时会被拆分成一个单独的子程序。例如
sub new {
my ($class, $input) = @_;
my $self = {};
bless $self, $class; # $self is an object now
$self->_init($input); # on which methods can be called
return $self;
}
sub _init {
my ($self, $args) = @_;
# Check arguments, work out defaults (etc),
# then assign to self as appropriate
%$self = %$args;
}
其中代码通过引用写入 "back",以便更新 new
中的 $self
。
这应该与普通方法调用一起使用
my $new_obj = P_module->new({key => 'abc', other => '...'});
和不使用间接表示法 new P_module
。构造函数,主要称为 new
(只是根据习惯——你可以随意称呼它),是一个普通的子特殊,只是因为它 bless
是一个引用(通常是一个散列引用),因此被传递class 名称而不是对象。因此它 "knows" 它的包并且是一个对象。
文学:perlmod (a class is a package), tutorial perlootut, and reference perlobj.
一旦您熟悉了 Perl 的内置面向对象功能(我建议您这样做),有许多模块可以使所有这些(以及更多)操作变得更容易。