Вопросы об одноименном мета-объекте - PullRequest
0 голосов
/ 06 января 2012

Просто прочитайте perltooc, где автор объясняет одноименный мета-объект. У меня есть несколько вопросов по этому поводу, которые я не нашел, выполнив поиск ...

1. Хэш должен быть назван как объект, но если имя объекта, если что-то вроде My :: Good :: Class, каким будет имя для одноименного хеша для него? Я попробовал:

 package My::Good::Class
 our %Class = ( some_data => 1 );
 sub getEpoHash {
   my $class = shift;
   my $var = ref($class) || $class;
   no strict 'refs';
   return \%$var;
 }

в случае, если я напишу наш% Class ...; - это не работает, но если я напишу% My :: Good :: Class = ...; - оно работает. Я не понимаю этого! В этом случае Class является хэшем для пакета My :: Good ... или что?!

2. В статье приведен пример создания монадического класса с использованием одноименного метаобъекта. Но все примеры написаны без использования строгих! Нужно ли вставлять в каждую функцию строгие ссылки перед использованием $ self, или есть другие способы переписать ее с использованием строгого?

Вот пример:

package Cosmos;
%Cosmos = ();
# accessor method for "name" attribute
sub name {
    my $self = shift;
    $self->{name} = shift if @_;
    return $self->{name};
}
# read-only accessor method for "birthday" attribute
sub birthday {
    my $self = shift;
    die "can't reset birthday" if @_; # XXX: croak() is better
    return $self->{birthday};
}
# accessor method for "stars" attribute
sub stars {
    my $self = shift;
    $self->{stars} = shift if @_;
    return $self->{stars};
}
# oh my - one of our stars just went out!
sub supernova {
    my $self = shift;
    my $count = $self->stars();
    $self->stars($count - 1) if $count > 0;
}
# constructor/initializer method - fix by reboot
sub bigbang {
    my $self = shift;
    %$self = (
        name => "the world according to tchrist",
        birthday => time(),
        stars => 0,
    );
    return $self; # yes, it's probably a class. SURPRISE!
}
# After the class is compiled, but before any use or require
# returns, we start off the universe with a bang.
__PACKAGE__ -> bigbang();

Ответы [ 2 ]

2 голосов
/ 06 января 2012

Текущая версия perltooc строго совместима, вы, вероятно, смотрите старую версию.

http://perldoc.perl.org/perltooc.html#The-Eponymous-Meta-Object

Лучшие практики со временем менялись, и для многих старых примеров кода потребуется несколько no strict 'refs', чтобы заставить их работать со стриктурами.

Относительноодноименный хеш для пакета, если у вас есть пакет с именем My::Good::Class, и вы рассматриваете эту строку как хеш (со строгим отсутствием ссылок), вы ссылаетесь на хеш %Class в пакете My::Good.

1 голос
/ 26 марта 2012

Я был так же растерян, как и Питер, поэтому я написал это:

use strict;
use warnings;

sub describe
{
    my ($class) = @_;

    # Ensure class variable hash name contains "::"
    my $cv = $class . ($class !~ /::/ && "::${class}");
    # Convert symbolic ref to "hard" ref
    no strict "refs";
    $cv = \%$cv;
    use strict;
    print "$class ($cv): \"", $cv->{description}, "\"\n\n";
}

package Simple;

# "our" creates a variable in the current package
# so "our %Simple" is the same as "%Simple::Simple".

# our %Simple = (description => "Simple's package is " . __PACKAGE__);
# print "\%Simple at ", \ %Simple, "\n";

%Simple::Simple = (description => "Simple's package is " . __PACKAGE__);
print "\%Simple::Simple at ", \ %Simple::Simple, "\n";

main::describe __PACKAGE__;

package More::Complex;

%More::Complex =
    (description => "More::Complex's package is " . __PACKAGE__);

print "\%More::Complex at ", \ %More::Complex, "\n";

main::describe __PACKAGE__;

Это показывает, что когда в пакете Simple выражение our %Simple = ... фактически означает то же самое, что %Simple::Simple = ....

Примеры в perltooc.html скрывают это, потому что они никогда не пытаются ссылаться на %Simple вне его пакета.Почему вы делаете то, что вы спрашиваете?Потому что в реальном мире вы не дублируете код доступа к переменным класса в каждом пакете, а вместо этого они наследуют его от некоторого суперкласса.Код суперкласса должен знать, что переменная класса для класса Simple равна %Simple::Simple, как в моем методе describe (своего рода).

Эта маленькая скрытая бородавка заставляет меня задуматься, непроще иметь фиксированное имя для переменных класса, таких как %Simple::class_varibles, %More::Complex::class_variables, даже если вы не выглядите настолько умно, используя слово «одноименный»: -).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...