【问题标题】:What is an overriden method in Perl?Perl 中的重写方法是什么?
【发布时间】:2013-06-19 08:30:18
【问题描述】:

这个问题是关于SUPER 类的。

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

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

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

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

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

我只能说:

$object = Classname -> new ();

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

【问题讨论】:

  • 不,这完全不是——任何答案基本上都会重复perldoc.perl.org/perlobj.html
  • 你从中学到了什么?可能有更好的书/教程/网站等适合您。在您更熟悉基本的 OO 概念和子类化 - 编辑、哦和方法参数之前,您不应该真正需要 'SUPER::'!
  • 您不会因为对单个问题投反对票而被禁止。无论如何,我认为perldoc perlootut 可能是一本好书。在Inheritance section 下有一个方法覆盖的示例。这不是你想的那样。
  • @BelmarkCaday - 投票本身不会让人们被禁止(尽管如果你发布 100 个问题,每个问题 -5,那可能)。它们表明人们不喜欢你的问题质量——基本上,你不是问有趣的编程问题,而是要求人们向你解释 OOP 001(甚至不是 101)的基础知识; 似乎自己没有做任何研究(您是否在 Google 上搜索过“子类/超类/OOP”?)。是的,获得太多反对票可能会导致人们对回答你的问题失去兴趣,即使是更有趣的问题(你确实有)
  • 重复我对您看到的第一个问题的第一个评论,首先阅读一般的 OOP(至少是一篇 Wiki 文章或一本好书),您会受益匪浅,并且然后从更基础的 Perl 材料开始(甚至可能是学习 Perl 而不是编程,根据这个问题的评论链接,至少加上 perldoc 上的一些文档)。

标签: perl oop


【解决方案1】:

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

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

这个 UML 图显示 Child 继承自 ParentAParentB,例如通过代码

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

现在,ChildParentA 继承了 foo 方法,从 ParentB 继承了 bar

如果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;

SaddledHorse.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。如果我们在Child 上调用bar 方法,则会查找该方法

  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)

【讨论】:

  • 在我阅读您的答案之前,我要感谢您在这里回答我的愚蠢问题所付出的努力。我相信我正处于一个叫做学习曲线的阶段。谢谢谢谢。
  • 我不能只说里面saddledhorse.pmHorse->new(%args,saddled=>1);吗?
  • 这是一个非常复杂的例子。不需要多重继承。 Base::fooChild::foo 就足够了。
  • @BelmarkCaday 是的,这个例子很糟糕,但我想表明一个子类可以有不同的默认值。一个更好但更复杂的示例可能涉及 GUI 编程。 MyFrame 可以从 Frame 继承,例如指定默认标题和布局。
  • @DVK 与 Perl 无关。一般用作类型论中的subtyping关系。作为它的一个变体,Ruby 使用< 来表示类定义中的继承。子类型关系是自反和传递的(这不适用于鸭子类型)。在大多数类型系统中,它是反对称的,因此对所有类型都施加了偏序。
【解决方案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 等)使其更具可读性 - 通过调用“覆盖”、“之前”、“之后”、“围绕”等功能来改变继承的方法

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-04-16
    • 1970-01-01
    • 2013-05-12
    • 1970-01-01
    • 2013-06-03
    • 1970-01-01
    • 2020-10-06
    相关资源
    最近更新 更多