Импорт функций / подпрограмм в подкласс

Я использую 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;

Тот же вывод, что и в предыдущем примере.

Другие вопросы по тегам