调用SUPER :: new()

sim*_*que 4 oop perl base-class

我已经看到了两种new在派生类中实现该方法的方法.

方法一:

sub new {
    my $invocant = shift;
    my $class   = ref($invocant) || $invocant; 
    my $self = {};
    bless($self, $class);
    $self = $self->SUPER::new( @_ );
    return($self);
}
Run Code Online (Sandbox Code Playgroud)

方法二:

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);
}
Run Code Online (Sandbox Code Playgroud)

我不确定我明白它的区别.有人可以解释一下吗?


根据您的评论和答案,我可以看到该ref()部分很糟糕.

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

在另一方面,第二实例中,基对象是从类的创建SUPER小号new方法和被祝福入新的类.

这两种方式有什么区别?看起来第一个用基础对象覆盖对象.第二个似乎是"双重祝福".我糊涂了.

Dal*_*aen 7

为什么不呢:

sub new {
    my $class = shift;
    my $self = $class->SUPER::new(@_);
    $self->do_some_additional_init();
    return $self;
};
Run Code Online (Sandbox Code Playgroud)

- 唯一的例外是层次结构中最深的基类,它应该调用bless $self, $class;或者可以调用my $self = fields::new($class);use fields.


pil*_*row 5

更新

你问:

这两种方式有什么区别?看起来第一个用基础对象覆盖对象.第二个似乎是"双重祝福".我糊涂了.

请记住.您展示的两种方法中的每一种本身都会混淆,也不应该模拟.

方法一将DerivedClass类的对象保存为存在,然后使用该对象调用某个AncestorClass的allocator/constructor,替换它自己.现在,AncestorClass :: new也可能使用了不幸的ref($yuck) || $yuck习语,这意味着新对象将被祝福到DerivedClass中.因此,一个DerivedClass对象用于构造另一个以替换它.可疑.

如果接收者是一个对象,方法二返回其接收者($ self).(注意,ref($self)只需要检查一次就会检查两次.)也就是说,在方法二下$o->new()返回相同的内容$o.如果接收者不是对象而是类名,也就是说,如果我们调用了DerivedClass->new,则调用AncestorClass :: new.但是超类'方法的第一个参数是'DerivedClass',并且可能超类不对其bless包名进行硬编码,因此随后的重新祝福毫无意义.

只是不要担心这些例子.相反,请咨询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.
Run Code Online (Sandbox Code Playgroud)

方法二是(我认为)这种令人困惑的做法的解决方法.如果被调用, 您的方法二将返回相同的对象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.
Run Code Online (Sandbox Code Playgroud)

不要使用任何一种.:)可能有一些应用程序,其中任何一个上述语义都很有意义.我只是不会new()在那些应用程序中命名该方法...