What is an overriden method in Perl?

2019-09-20 04:59发布

问题:

This question is about the SUPER class.

When would an "overridden method" happens?

So say when I instantiate a class:

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

Is that what you call an overridden method? the new method's overridden values?

If so then, why would I want to use that SUPER class?

I can just say:

$object = Classname -> new ();

I have the original method again. Can someone clarify this for me?

回答1:

Inheritance describes a parent-child relationship. Everything the parents can do, the child class can too. E.g.

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

This UML diagram shows that Child inherits from ParentA and ParentB, e.g. via the code

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

Now, Child has inherited the method foo from ParentA and bar from ParentB.

If Child defines a foo method itself, Child->foo would call this method, and not one of the methods of the parent classes. It is then said that the foo method is overridden.

Example

When subclassing, it is often useful to re-use the constructor of the parent. But sometimes, additional processing has to be done. In this case, a subclass wants to provide a different default argument:

Horse.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;

Note how the $class is propagated to bless the reference into the correct class. The SUPER package is only available inside a package that defines an inheritance relationship, and is arguably broken. If you need SUPER, you usually want to use Moose, where a method that is explicitly said to override can call the super method with the super function.

Edit: A note on fully qualifed method names

If you call a method on a package/object, the correct method is resolved at runtime. If you look at the top of this answer to the inheritance diagram, you can see that ParentB defines bar. If we invoke the bar method on a Child, that method is looked for

  1. in Child,
  2. in ParentA, and
  3. in ParentB, where it is found.

This is called “method resolution”, and is a tricky issue in itself.

If we pass a fully qualifed subroutine name as the method, no resolving happens, and the sub is called directly. E.g. Child->foo would resolve the method to ParentA::foo, so that call would be roughly equal to ParentA::foo("Child"). If hower we do

Child->ParentB::foo();

we get the effect of ParentB::foo("Child"). The syntax with the -> is superfluous, but reminds us that we are kind of using a method on an object. Therefore, I preferred to write

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

in the SaddledHorse example, even if this is only elaborate syntax for

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

which resolves to

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


回答2:

Do you have more context? It's probably referring to a method overridden in a subclass.

e.g.

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"

The calling of SUPER::foo is optional - the method can just override foo and replace it's behaviour or augment it, either by doing work before SUPER::foo or after.

More modern OO perl, (e.g. using Moose, Moo, etc) makes this more readable - with calls to features such as 'override', 'before', 'after', 'around' etc to alter inherited methods



标签: perl oop