Как я создаю класс в оперативной памяти и затем включаю его в Perl?

Я попытался использовать метод функции из jbaron выше, но обнаружил, что мне нужно сохранить исходный массив без изменений для последующего использования, и создать новый массив, подобный этому:

var newArray = referenceArray;

, очевидно, создает по ссылке вместо значение, потому что, когда я удалил элемент из newArray, referenceArray также удалил его. Поэтому я решил каждый раз создавать новый массив следующим образом:

function newArrRemoveItem(array, item, newArray){
    for(var i = 0; i < array.length; i++) {
        if(array[i]!=item){
            newArray.push(array[i]);
        }
    }
}

Затем я использую его следующим образом в другой функции:

var vesselID = record.get('VesselID');
var otherVessels = new Array();
newArrRemoveItem(vesselArr,vesselID,otherVessels);

Теперь vesselArr остается неизменным, а каждый раз - выполнить приведенный выше код, массив otherVessels включает в себя все, кроме самого последнего элемента vesselID.

5
задан 5 revs, 3 users 66% 10 October 2011 в 00:39
поделиться

4 ответа

Here is a version which works:

#!/usr/bin/perl

use strict;
use warnings;

my $class = 'Frew';

{
    no strict 'refs';
    *{ "${class}::INC" } = sub {
        my ($self, $req) = @_;
        return unless $req eq  $class;
        my $data = qq{
            package $class;
            sub foo { print "test!\n" };
            1;
        };
        open my $fh, '<', \$data;
        return $fh;
    };
}

my $foo = bless { }, $class;
unshift @INC, $foo;

require $class;
$class->foo;

The @INC hook gets the name of the file (or string passed to require) as the second argument, and it gets called every time there is a require or use. So you have to check to make sure we're trying to load $classname and ignore all other cases, in which case perl continues down along @INC. Alternatively, you can put the hook at the end of @INC. This was the cause of your recursion errors.

ETA: IMHO, a much better way to achieve this would be to simply build the symbol table dynamically, rather than generating code as a string. For example:

no strict 'refs';
*{ "${class}::foo" } = sub { print "test!\n" };
*{ "${class}::new" } = sub { return bless { }, $class };

my $foo = $class->new;
$foo->foo;

No use or require is necessary, nor messing with evil @INC hooks.

10
ответ дан 18 December 2019 в 14:49
поделиться

В качестве простого примера того, как это сделать, прочтите исходный код Class :: Struct .

Однако, если мне понадобится возможность динамически создавать классы для какой-нибудь производственный код, я бы посмотрел на MooseX :: Declare, как предлагает jrockway.

0
ответ дан 18 December 2019 в 14:49
поделиться

A Perl class is little more than a data structure (usually a hashref) that has been blessed into a package in which one or more class methods are defined.

It is certainly possible to define multiple package namespaces in one file; I don't see why this wouldn't be possible in an eval construct который компилируется во время выполнения (см. perlfunc для двух разных eval форм).

#!/usr/bin/perl

use 5.010;
use strict;
use warnings;
use Data::Dumper;

eval q[
    package Foo;
    sub new {
        my ( $class, %args ) = @_;
        my $self = bless { %args }, $class;
        return $self;
    }
    1;
];
die $@ if $@;

my $foo = Foo->new(bar => 1, baz => 2) or die;

say Dumper $foo;
-3
ответ дан 18 December 2019 в 14:49
поделиться

Я делаю это:

use MooseX::Declare;

my $class = class {
    has 'foo' => (is => 'ro', isa => 'Str', required => 1);
    method bar() {
        say "Hello, world; foo is ", $self->foo;
    }
};

Затем вы можете использовать $ class, как любой другой метакласс:

my $instance = $class->name->new( foo => 'foo bar' );
$instance->foo; # foo-bar
$instance->bar; # Hello, world; foo is foo-bar

и т. Д.

Если вы хотите динамически генерировать классы во время выполнения, вам нужно создать соответствующий метакласс, создайте его экземпляр, а затем используйте экземпляр метакласса для создания экземпляров. Базовый ОО. Class :: MOP обрабатывает все детали за вас:

my $class = Class::MOP::Class->create_anon_class;
$class->add_method( foo => sub { say "Hello from foo" } );
my $instance = $class->new_object;
...

Если вы хотите сделать это самостоятельно, чтобы вы могли тратить свое время на отладку чего-либо, возможно, попробуйте:

sub generate_class_name {
    state $i = 0;
    return '__ANON__::'. $i++;
}

my $classname = generate_class_name();
eval qq{
    package $classname;
    sub new { my \$class = shift; bless {} => \$class }
    ...
};

my $instance = $classname->new;
6
ответ дан 18 December 2019 в 14:49
поделиться
Другие вопросы по тегам:

Похожие вопросы: