Importing functions / routines into a subclass
I am using Moops
and I would like something like this to work:
use Moops;
class A {
fun f {
print "yay,f!\n";
}
}
class B extends A {
fun g {
f();
}
}
B->g(); # should print 'yay, f!'
Instead, this gives:
Undefined subroutine &B::f called at static-functions-lexical-scope.pl line 11.
I can "fix" this by inheriting from Exporter
in A
and use
in B
as follows:
class A extends Exporter {
our @EXPORT = qw(f);
fun f {
print "yay,f!\n";
}
}
class B extends A {
use A;
fun g {
f();
}
}
This seems a little cumbersome, but gets worse if A
defined in another file. Then I would have to add a second use A
( require
won't do) outside B
like so:
use A;
class B extends A {
use A;
fun g {
f();
}
}
Is there a way to more elegantly use the lexical include (exported) functions?
source to share
First, thanks for using Moops! :-)
Secondly, it's probably a bad idea to name classes "B" in tests and examples. There's a module called B
that comes with Perl, and Moops actually uses it!
Coming to your actual question, generally speaking with classes, you should be thinking method
, not fun
. The method commands respect for inheritance; function calls are not executed.
use Moops;
class AAA {
method f {
say "yay,f!";
}
}
class BBB extends AAA {
method g {
$self->f;
}
}
BBB->g;
Outputs:
yay,f!
If you want a library of convenience functions to be available both in AAA
and out BBB
, split these convenience functions into a separate package:
use Moops;
namespace MyUtils {
use Exporter::Shiny qw( f );
fun f {
say "yay,f!";
}
}
class AAA {
use MyUtils -all;
method m1 {
f();
}
}
class BBB extends AAA {
use MyUtils -all;
method m2 {
f();
}
}
BBB->m1;
BBB->m2;
Outputs:
yay,f! yay,f!
You can even go a little further and expand Moops from the inside out. The following example defines a property :utils
that can be added to classes:
use Moops;
namespace MyUtils {
use Exporter::Shiny qw( f );
fun f {
say "yay,f!";
}
}
role Moops::TraitFor::Keyword::utils {
around generate_package_setup {
return (
$self->$next(@_),
'use MyUtils -all;',
);
}
}
class AAA :utils {
method m1 {
f();
}
}
class BBB extends AAA :utils {
method m2 {
f();
}
}
BBB->m1;
BBB->m2;
The same conclusion as in the previous example.
source to share