2016-10-20 4 views
1

Я прошу вас о помощи на материалах Perl.Сделайте класс на Perl (класс :: Std)

настоящее время у меня мой код работает хорошо, создавая новый объект, а затем использовать его, чтобы запустить функцию, но я хотел бы использовать более современные способы кодирования с Perl (используя class:Std и интегрированный BUILD/START функции)

Так прямо сейчас мой код выглядит, что я называю new с пути в лог-файл, а затем запустить одну функцию:

# Called from another perl script 
use MyClass; 
my $Obj = MyClass->new('/usr/me/path.log'); 
$Obj->run(); 

# My module 
package MyClass; 

sub new { 
    shift if (defined($_[0] eq 'MyClass')); 
    my %args = validate(@_,{ LogPath => { type => SCALAR, optional => 0 }, }); 

    my $self; 
    $self->{plistPath} = $_[1]; 
    return bless $self; 
} 

sub run { 
    my $self = shift; 
    ... 
    ... 
} 

и то, что я хотел бы иметь это, например, что:

use Class::Std 

sub BUILD { 
    my $self = shift; 
    my $ident = shift; 

    my %args = validate(@_, { LogPath => { type => SCALAR, optional => 0 }, }); 

    print "My log path:".$args{LogPath}."\n"; 

    $self->{logPath} = $args{LogPath}; 

    return bless $self; 
} 

sub run { 
    my $self = shift; 

    print $self->{logPath}; 

    .... 
} 

Но это не работает, оно хорошо печатает путь журнала в BUILD (я просто хотел проверить здесь, если он работает), но я не могу его зарегистрировать в $self->{logPath}, чтобы использовать его в мои другие функции. Это говорит мне, что это не ссылка Хэша.

Из учебников, которые я сделал, я думаю, что BUILD не должен возвращать $self, поскольку он создается автоматически с помощью , но я не знаю, как это сделать.

Ваша помощь будет принята с благодарностью, если у вас есть какие-либо советы.

Большое спасибо, Тим.

+2

Я бы порекомендовал против использования 'Class :: STD' ... Это было частью наизнанку класса вещь, которая была краткой причудой. Это делает все громоздким. –

ответ

5

Поскольку вы изучаете более современный стиль, могу ли я рекомендовать вам дать Moose или Moo попытке, поскольку они пытаются упростить объектно-ориентированный опыт Perl, поскольку мы делаем его намного более мощным. Эти модули были введены после появления Class::Std и представляют собой более современный подход к созданию объекта. Различия между Moose/Moo (и некоторыми другими, такими как Mo или M (joke)) - это то, что Moose дает вам полную силу Object Meta Programming, в то время как Moo стремится к меньшей мощности, но более высокой скорости.

Вот пример кода, с помощью Moo:

test.pl

#!/usr/bin/env perl 

use strict; 
use warnings; 

use MyClass; 
my $obj = MyClass->new(LogPath => '/var/log/messages'); 
$obj->run(); 
1; 

MyClass.pm

package MyClass; 
use Moo; # Moose/Mouse/Moo 

has LogPath => (
    is => 'ro', # Read Only 
    required => 1, # Required 
    isa => sub { 
     my ($path) = @_; 
     die "LogPath must be a SCALAR" if (ref $path); 
     die "LogPath [$path] must be a real path" unless -f $path; 
    }, 
); 

sub run { 
    my ($self) = @_; 
    print "MyClass::run()\n"; 
    my $path = $self->LogPath(); 
    print "About to do something with LogPath [ $path ]\n"; 
} 

1; 

Выход

perl test.pl 
MyClass::run() 
About to do something with LogPath [ /var/log/messages ] 

В соответствии с просьбой, для сравнения, здесь тот же объект, но на этот раз создан при Class::Std. Пожалуйста, обратите внимание, сколько еще код/​​шаблонный требуется с Class::Std раствором против Moo:

test_class_std.pl

#!/usr/bin/env perl 

use strict; 
use warnings; 

use MyClassStd; 
my $obj = MyClassStd->new({ LogPath => '/var/log/messages' }); 
$obj->run(); 
print $obj->get_description() . "\n"; 

MyClassStd.вечера

package MyClassStd; 

use Class::Std; 

# Create storage for object attributes... 
# The syntax '%foo : ATTR' applies the attribute named ATTR to the hash %foo. 
# For more info on how this works, see: perldoc attributes 

# Create one hash per attribute, these will be private to the class 
my %log_paths : ATTR; 

# These fields will be available via $obj->get_foo() methods 
my %public_data : ATTR; 

# Handle initialization of objects of this class... 
sub BUILD { 
    my ($self, $object_id, $args) = @_; 
    my $path = check_path($args->{ LogPath }); 
    $log_paths{ $object_id } = $path; 
    $public_data{ $object_id }{ description } = "LogPath is set to [ $path ]"; 
} 

# Handle cleanup of objects of this class... 
sub DEMOLISH { 
    my ($self, $object_id) = @_; 
    # Objects will be removed from the hashes automatically 
    # Add any other cleanup code here 
} 

# Handle unknown method calls... 
sub AUTOMETHOD { 
    my ($self, $object_id, @args) = @_; 

    my $method_name = $_; # Method name passed in $_ 
    # Return any public data... 
    if ($method_name =~ m/^get_(.*)/) { 
     my $get_what = $1; 
     return sub { 
      return $public_data{$object_id}{$get_what}; 
     } 
    } 

    warn "Can't call $method_name on ", ref $self, " object"; 

    return; # The call is declined by not returning a sub ref 
} 

sub run { 
    my ($self) = @_; 

    print "MyClassStd::run()\n"; 
    my ($path) = $log_paths{ ident $self }; 
    print "About to do something with LogPath [ $path ]\n"; 

} 

sub check_path { 
    my ($path) = @_; 

    die "LogPath must be a SCALAR" if (ref $path); 
    die "LogPath [ $path] must be a real path" unless -f $path; 

    return $path; 
} 

1; 

Выход

MyClassStd::run() 
About to do something with LogPath [ /var/log/messages ] 
LogPath is set to [ /var/log/messages ] 
+1

С момента стартапа, который раньше имел Лось, больше нет, нет настоящих оснований рекомендовать Mouse в это время. [Any :: Moose] (https://v1.metacpan.org/pod/Any::Moose), который использовался для выбора между ними, был устаревшим в пользу Moo. – simbabque

+0

На веселой ноте почему бы не включить Мо и [M] (https://v1.metacpan.org/pod/M) тоже? ;-) – simbabque

+0

Конечно, почему бы и нет ... Я добавил их. – xxfelixxx