开发者

Define the method in the constructor of class in perl

I am reading code snippets like below:

sub new {
        my $pkg  = shift;
        my $args = shift;

        my @keys = keys %$args;

        my $self = bless \%{$args}, $pkg;
        $self->{'__properties'} = \@keys;

        my $class = ref($self);

        foreach my $meth (@keys) {

                if (! $self->can($meth)) {

                        no strict "refs";

                        *{ $class . "::" . $meth } = sub {开发者_JS百科
                                my $instance = shift;
                                return $instance->{$meth};
                        };
                }
        }

        return $self;
}

In the foreach loop, it seems that it creates some methods according to the parameters. There are two lines which I don't understand.Could someone help me? What's the * and {} used for?

no strict "refs";
*{ $class . "::" . $meth }

Best Regards,


This creates a symbol table alias.
The right side contains a reference to a function, so Perl will alias it to the subroutine $meth in the package $class.

See Symbol Tables in perlmod.


As eugene y have already explained, those lines manipulate the symbol table. In practical terms, they do so in order to create read-only accessor methods in the class based on whatever arbitrary list of attributes get passed into the constructor:

#!/usr/bin/env perl

use strict;
use warnings;
use 5.10.0;

package SomeClass;

sub new {
    my $pkg  = shift;
    my $args = shift;

    my @keys = keys %$args;

    my $self = bless \%{$args}, $pkg;
    $self->{'__properties'} = \@keys;

    my $class = ref($self);

    foreach my $meth (@keys) {

        if (!$self->can($meth)) {

            no strict "refs";

            *{$class . "::" . $meth} = sub {
                my $instance = shift;
                return $instance->{$meth};
            };          
        }       
    }   

    return $self;
}

package main;

my $foo = SomeClass->new({foo => 5});   # Creates SomeClass::foo

say $foo->foo;  # 5

my $bar = SomeClass->new({foo => 3, bar => 7});   # Creates SomeClass::bar

say $bar->foo;  # 3
say $bar->bar;  # 7
say $foo->bar;  # undef - ::bar was added to all instances of SomeClass

say $foo->baz;  # Boom!  No such method.

Personally, I think this is questionable OO practice (a class should generally have a known set of attributes instead of potentially adding new ones each time an instance is constructed), but that's what it does...

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜