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?
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
- in
Child
,
- in
ParentA
, and
- 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)
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