【问题标题】:Invocation of SUPER::new()调用 SUPER::new()
【发布时间】:2012-06-12 15:46:37
【问题描述】:

我见过两种在派生类中实现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);
}

我不确定我是否理解其中的区别。谁能解释一下?


从您的 cmets 和答案中,我可以看到 ref() 部分很糟糕。

但是SUPER::new(@_) 的使用呢?在第一个示例中,hashref 被祝福到派生类中,然后该对象的 SUPERnew 被调用并保存到同一个对象中。

另一方面,在第二个示例中,基对象是从类的 SUPERs new 方法创建的,并被祝福到新类中。

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

【问题讨论】:

标签: perl oop base-class


【解决方案1】:

为什么不只是:

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

【讨论】:

    【解决方案2】:

    更新

    你问:

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

    振作起来。您展示的这两种方法中的每一种本身都令人困惑,不应该效仿。

    方法一祝福 DerivedClass 类的对象存在,然后使用该对象调用某个 AncestorClass 的分配器/构造器,替换自身。现在,AncestorClass::new 可能也使用了不幸的ref($yuck) || $yuck 成语,这意味着新对象将被祝福到DerivedClass。因此,一个 DerivedClass 对象用于构造另一个来替换它。可疑。

    如果接收者是一个对象,方法二返回它的接收者($self)。 (注意ref($self) 只需要检查一次时会检查两次。)也就是说,$o->new() 在方法二下返回完全相同的$o。如果接收者不是一个对象而是一个类名,也就是说,如果我们调用了DerivedClass->new,那么就会调用 AncestorClass::new。但是超类'方法的第一个参数是'DerivedClass',而且想必超类并没有硬编码它的blessed包名,所以后面的重新加持是没有意义的。

    不用担心这些例子。相反,请咨询perlobjperlootut,以安全和理智地使用 SUPER。

    原答案

    哎呀,我的眼睛!

    正如 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(),您的方法二将返回完全相同的对象

    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()...

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-08-08
      • 2015-04-02
      • 2019-04-11
      • 1970-01-01
      • 2019-02-05
      相关资源
      最近更新 更多