Импорт функций / подпрограмм в подкласс
Я использую Moops
и я хотел бы, чтобы что-то вроде этого работало:
use Moops;
class A {
fun f {
print "yay,f!\n";
}
}
class B extends A {
fun g {
f();
}
}
B->g(); # should print 'yay, f!'
Вместо этого это дает:
Undefined subroutine &B::f called at static-functions-lexical-scope.pl line 11.
Я могу исправить это, унаследовав от Exporter
в A
и use
заявление в B
вот так:
class A extends Exporter {
our @EXPORT = qw(f);
fun f {
print "yay,f!\n";
}
}
class B extends A {
use A;
fun g {
f();
}
}
Это кажется немного громоздким, но становится хуже, если A
определяется в другом файле. Тогда я должен был бы добавить секунду use A
(require
не будет делать) за пределами B
вот так:
use A;
class B extends A {
use A;
fun g {
f();
}
}
Есть ли способ заставить лексические функции включения (экспортируемых) работать более элегантно?
1 ответ
Во-первых, спасибо за использование Moops!:-)
Во-вторых, это плохая идея называть классы "B" в тестах и примерах. Там есть модуль под названием B
это идет с Perl, и Moops фактически использует это!
Подходя к вашему актуальному вопросу, вообще говоря с классами, вы должны думать method
скорее, чем fun
, Метод вызывает уважение наследования; вызовы функций не делают.
use Moops;
class AAA {
method f {
say "yay,f!";
}
}
class BBB extends AAA {
method g {
$self->f;
}
}
BBB->g;
Выходы:
yay,f!
Если вы хотите, чтобы библиотека удобных функций была доступна в обоих AAA
а также BBB
затем разделите эти вспомогательные функции на отдельный пакет:
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;
Выходы:
yay,f!
yay,f!
Вы даже можете пойти немного дальше и расширить Moops изнутри. В следующем примере определяется :utils
черта, которая может быть добавлена к классам:
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;
Тот же вывод, что и в предыдущем примере.