我看到了在派生类中实现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(@_)的使用呢?在第一个示例中,哈希and被授予派生类,然后调用该对象的SUPER的new并将其保存到同一个对象中。
另一方面,在第二个示例中,从类的SUPER的new方法创建一个基本对象,这个对象被赋予新的类。
这两种方式有什么区别?它看起来像是第一个用基对象覆盖对象。第二种似乎是“双重祝福”。我很困惑。
发布于 2012-06-08 15:20:50
更新
你问:
这两种方式有什么区别?它看起来像是第一个用基对象覆盖对象。第二种似乎是“双重祝福”。我很困惑。
振作起来。您所展示的两种方法本身都是混乱的,两者都不应该被模仿。
方法将类DerivedClass的对象赋值,然后使用该对象调用某些AncestorClass的分配器/构造函数,替换自身。现在,AncestorClass::new可能也使用了不幸的ref($yuck) || $yuck成语,这意味着新对象将被祝福为DerivedClass。因此,使用一个DerivedClass对象来构造另一个对象来替换它。可疑。
如果接收方是对象,则方法2返回其接收器($self)。(注意,当ref($self)只需要检查一次时,它会被检查两次。)也就是说,$o->new()在方法2下返回完全相同的$o。如果接收方不是对象而是类名,也就是说,如果我们调用了DerivedClass->new,则调用AncestorClass::new。但是,超类‘方法’的第一个参数是‘派生类’,并且假定超类不会硬编码它的blessed包名,因此后续的重新祝福是没有意义的。
只是不要担心这些例子。相反,请咨询佩洛布和围观的安全和理智的用途超级。
原始答案
啊,我的眼睛!
正如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.第二种方法(我认为)是对这种令人困惑的做法的解决办法。如果调用,则方法2将返回完全相同的对象。
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() .
发布于 2012-06-08 19:57:36
为什么不只是:
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。
https://stackoverflow.com/questions/10951292
复制相似问题