-1

这个问题是关于SUPER班级的。

什么时候会发生“覆盖的方法”?

所以当我实例化一个类时说:

$object = Classname -> new (some => 'values');

这就是你所说的覆盖方法吗?新方法的覆盖值?

如果是这样,我为什么要使用SUPER该类?

我只能说:

$object = Classname -> new ();

我又有原来的方法了。有人可以为我澄清一下吗?

4

2 回答 2

3

继承描述了父子关系。父母能做的一切,孩子班也能。例如

ParentA    ParentB
=======    =======
foo()      foo()
-------    bar()
     |     -------
     |   /
    Child
    =====

此 UML 图显示从和Child继承,例如通过代码ParentAParentB

package Child;
use parent "ParentA";
use parent "ParentB"

现在,Child继承了foofromParentAbarfrom的方法ParentB

如果自己Child定义了一个foo方法,Child->foo就会调用这个方法,而不是父类的方法之一。然后说该foo方法被覆盖

例子

子类化时,重用父类的构造函数通常很有用。但有时,必须进行额外的处理。在这种情况下,子类想要提供不同的默认参数:

马.pm

package Horse;
use strict; use warnings;

sub new {
  my ($class, %args) = @_;
  return bless {
    legs => 4,
    saddled => 0,
    %args,
  } => $class;
}

1;

鞍马.pm

package SaddledHorse;
use strict; use warnings;

use parent 'Horse';

# This override the inherited “new”
sub new {
  my ($class, %args) = @_;
  # the “SUPER” pseudo-package points to the parent
  return $class->SUPER::new(%args, saddled => 1);
}

1;

请注意如何$class传播以将引用保佑到正确的类中。该SUPER包仅在定义继承关系的包中可用,并且可以说是损坏的。如果需要SUPER,您通常希望使用 Moose,其中明确表示要覆盖的方法可以使用该super函数调用超级方法。

编辑:关于完全限定方法名称的注释

如果您在包/对象上调用方法,则会在运行时解析正确的方法。如果您查看此继承图答案的顶部,您会看到ParentB定义bar. 如果我们bar在 a 上调​​用该方法Child,则会查找该方法

  1. Child,
  2. ParentA, 和
  3. ParentB,它在哪里被发现。

这称为“方法解析”,本身就是一个棘手的问题。

如果我们将完全限定的子例程名称作为方法传递,则不会发生解析,而是直接调用 sub。例如Child->foo,将方法解析为ParentA::foo,因此调用大致等于ParentA::foo("Child")。如果我们这样做

Child->ParentB::foo();

我们得到 的效果ParentB::foo("Child")。带有 的语法->是多余的,但它提醒我们,我们有点在对象上使用方法。因此,我更喜欢写

$class->SUPER::new(%args, saddled => 1)

SaddledHorse示例中,即使这只是复杂的语法

# SUPER::new($class, %args, saddled => 1)  # pseudocode, won't actually run

解决为

Horse::new($class, %args, saddled => 1)
于 2013-06-19T08:54:57.173 回答
2

你有更多的上下文吗?它可能指的是子类中重写的方法。

例如

use feature 'say';

package A;

sub foo {
   say "A";
}

package B;
use base 'A';

# this is overriding 'foo' in A.
sub foo {
   my $class = shift;
   $class->SUPER::foo(); # calls A->foo(), but this is optional
   say "B";
}

B->foo(); # prints "A" then "B"

SUPER::foo 的调用是可选的 - 该方法可以foo通过在 SUPER::foo 之前或之后执行工作来覆盖和替换它的行为或增强它。

更现代的 OO perl,(例如使用 Moose、Moo 等)使其更具可读性 - 通过调用诸如“覆盖”、“之前”、“之后”、“围绕”等特性来改变继承的方法

于 2013-06-19T08:42:45.593 回答