我正在创建一个新对象,如下所示:
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}
甚至意味着什么?
答案 0 :(得分:6)
首先,
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
。
答案 1 :(得分:2)
你有理由拥有这个:
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);
答案 2 :(得分:0)
周围的花括号创建一个哈希引用或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子例程返回最后一个表达式的值,因此您的代码存在错误。您希望P_module::new
的最后一行是
bless ($obj, ref($pkg)||$pkg);
因为那将返回可以用来调用其他方法的祝福对象,例如,
my $new_obj = new P_module({key => 'abc'});
print $new_obj->other_method_that_you_must_define(), "\n";
答案 3 :(得分:0)
调用方法时,对象本身会在幕后传递;或者,如果子使用bless,则它是构造函数,而是传递类名。因此任何方法都接收对象或类名作为其第一个参数。其余的是明确传递给方法的参数。
你传递哈希引用 {...}
,什么是标量。所以这被分配给$input
,因为"非常"传递的类名称已分配给$pkg
。
该接口的构造函数带有哈希引用,通常最简单地写为
sub new {
my ($class, $input) = @_;
my $self = { %$input };
return bless $self, $class;
}
其中return
可以省略,因为返回了最后一个计算语句的返回值。最后两行可以写成return bless { %$input }, $class;
,并且(匿名)hashref被初始化,祝福它的包$class
(所以它是一个对象),然后返回。
请注意,您不必传递hashref;简单的哈希使得界面更清晰。如果可能还有其他参数,则需要使用引用, 使解析所有这些成为可能。
但是,您通常希望处理参数。例如,必须检查它们是否符合您的类支持的内容,而不是盲目地将用户传递的键分配给属性。如果你提供默认值,则计算出默认值,如果需要则检查值等等。
这种数据初始化有时会分成单独的子程序。例如
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;
}
代码写入"返回"通过引用,以便更新$self
中的new
。
这应该与普通方法调用一起使用
my $new_obj = P_module->new({key => 'abc', other => '...'});
使用间接表示法 new P_module
和不。构造函数,通常称为new
(只是通过自定义 - 你可以调用它你想要的),是一个普通的sub特殊,因为它bless
是一个引用(通常是一个哈希引用),因此通过类名而不是对象。因此,它知道"它的包装是一个对象。
文献:perlmod(一个类是一个包),教程perlootut和参考perlobj。
一旦您熟悉了Perl内置的面向对象设施,我建议您这样做,有许多模块可以让所有这些(以及更多)更容易实现。