我已经看到了两种在派生类中实现new
方法的方法。
方法一:
sub new {
my $invocant = shift;
my $class = ref($invocant) || $invocant;
my $self = {};
bless($self, $class);
$self = $self->SUPER::new( @_ );
return($self);
}
方法二:
sub new {
my $self = shift;
my $class = ref($self) || $self;
return $self if ref $self;
my $base_object = $class->SUPER::new(@_);
return bless ($base_object, $class);
}
我不确定我明白区别是什么。有人可以解释一下吗?
根据您的评论和回答,我可以看到ref()
部分不好。
但SUPER::new(@_)
的使用呢?在第一个示例中,hashref被保存到派生类中,然后调用该对象的SUPER
的{{1}}并保存到同一对象中。
另一方面,在第二个示例中,基类是从类的new
SUPER
方法创建的,并且可以保存到新类中。
这两种方式有什么区别?看起来第一个用基础对象覆盖对象。第二个似乎是“双重祝福”。我很困惑。
答案 0 :(得分:7)
为什么不呢:
sub new {
my $class = shift;
my $self = $class->SUPER::new(@_);
$self->do_some_additional_init();
return $self;
};
- 唯一的例外是层次结构中最深的基类,如果你bless $self, $class;
,可以调用my $self = fields::new($class);
或use fields
。
答案 1 :(得分:5)
<强>更新强>
你问:
这两种方式有什么区别?看起来第一个用基础对象覆盖对象。第二个似乎是“双重祝福”。我很困惑。
请记住。你展示的两种方法中的每一种本身都是混淆的,都不应该被模仿。
方法一将DerivedClass类的对象保存为存在,然后使用该对象调用某个AncestorClass的allocator / constructor,替换它自己。现在,AncestorClass :: new也可能使用了不幸的ref($yuck) || $yuck
成语,这意味着新对象将被祝福为DerivedClass。因此,一个DerivedClass对象用于构造另一个以替换它。可疑。
如果接收者是一个对象,方法二返回其接收者($ self)。 (请注意,ref($self)
只需要检查一次就会检查两次。)也就是说,$o->new()
会在方法二下返回相同的$o
。如果接收者不一个对象而是一个类名,也就是说,如果我们调用了DerivedClass->new
,则调用AncestorClass :: new。但是超类'方法的第一个参数是'DerivedClass',并且可能超类不对其bless
ed包名进行硬编码,因此随后的重新祝福毫无意义。
不要担心这些例子。相反,请咨询perlobj和perlootut,以便安全,有效地使用SUPER。
原始回答
Augh,我的眼睛!
正如daxim评论的那样,方法一是一种令人反感的方法,即允许一个人从一个现有对象的同一个类构造一个对象:
my $o1 = MethodOne->new();
my $o2 = $o1->new(); # $o2 is a clone of $o1. No, wait, it isn't!
# It's a brand new, "empty" object. Ha,
# fooled you.
方法二是(我认为)这种令人困惑的做法的解决方法。如果调用new()
,您的方法二将返回非常相同的对象。< / p>
my $o1 = MethodTwo->new();
my $o2 = $o1->new(); # $o2 is a new MethodTwo. No, wait, it isn't!
# It's a brand new object. No, wait, it isn't!
# It's a /exactly the same object/ as $o1. Ha,
# fooled you.
不要使用任何一种。 :)可能有一些应用程序,其中任何一个上述语义都很有意义。我只是不会在那些应用程序中命名该方法new()
...