调用SUPER :: new()

时间:2012-06-08 14:58:51

标签: perl oop base-class

我已经看到了两种在派生类中实现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方法创建的,并且可以保存到新类中。

这两种方式有什么区别?看起来第一个用基础对象覆盖对象。第二个似乎是“双重祝福”。我很困惑。

2 个答案:

答案 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包名进行硬编码,因此随后的重新祝福毫无意义。

不要担心这些例子。相反,请咨询perlobjperlootut,以便安全,有效地使用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() ...